2

I am trying to do a twitter visualization. I using curves to connect two points on the map. enter image description here

Here is the code which I am using for it. It has been taken from an example by Chrisir from the processing forums.

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

void draw() 
{
  // myCurveTest() ;
  PVector firstpoint = new PVector (120, 320, -30); 
  PVector secondpoint = new PVector (320, 220, -30);
  myCurve (firstpoint, secondpoint ) ;
  firstpoint = new PVector (420, 220, 30); 
  secondpoint = new PVector (620, 120, -30);
  myCurve (firstpoint, secondpoint ) ;
}


void myCurve (
PVector firstpoint, 
PVector secondpoint) {
  PVector beginningcontrolpoint = new PVector (120, firstpoint.y+1200, -30); 
  PVector endingcontrolpoint = new PVector (720, secondpoint.y+1200, -30); 
  myPointPVector(beginningcontrolpoint, color(255, 0, 0));
  myPointPVector(firstpoint, color(0, 0, 255));  
  myPointPVector(secondpoint, color(0, 0, 255));  
  myPointPVector(endingcontrolpoint, color(255, 0, 0));
  stroke (255);
  noFill();
  curve(
  beginningcontrolpoint.x, beginningcontrolpoint.y, beginningcontrolpoint.z, 
  firstpoint.x, firstpoint.y, firstpoint.z, 
  secondpoint.x, secondpoint.y, secondpoint.z, 
  endingcontrolpoint.x, endingcontrolpoint.y, endingcontrolpoint.z);
}


void myPointPVector (PVector test, color col1) {
  MyBox(test.x, test.y, test.z, 
  test.x+3, test.y, test.z, 
  9, 
  col1);
}

void MyBox(float x1, float y1, float z1, float x2, float y2, float z2, float weight, color strokeColour)
// was called drawLine; programmed by James Carruthers
// see http://processing.org/discourse/yabb2/YaBB.pl?num=1262458611/0#9
{
  PVector p1 = new PVector(x1, y1, z1);
  PVector p2 = new PVector(x2, y2, z2);
  PVector v1 = new PVector(x2-x1, y2-y1, z2-z1);
  float rho = sqrt(pow(v1.x, 2)+pow(v1.y, 2)+pow(v1.z, 2));
  float phi = acos(v1.z/rho);
  float the = atan2(v1.y, v1.x);
  v1.mult(0.5);
  pushMatrix();
  translate(x1, y1, z1);
  translate(v1.x, v1.y, v1.z);
  rotateZ(the);
  rotateY(phi);
  noStroke();
  fill(strokeColour);
  box(weight, weight, p1.dist(p2)*1.2);
  popMatrix();
}

I want to animated this 3D curve so that I can see them being drawn on the map. Can anyone help me out with this. I have tried everything from framecount to advanced animation libraried in processing but no luck yet :(

Thanks.

user2228512
  • 37
  • 1
  • 1
  • 8

3 Answers3

1

You may just calculate a parabola point by point, draw it using curveVertex and orbit it in 3D using translate and rotate, here an example (using 1.5.1/P3D/fontMode(SCREEN)):

float initial_x = -200;
float x =  initial_x;
float y;
float y_offset;
float r = 200;// change this to change the height of the parabola
ArrayList<PVector> pts = new ArrayList<PVector>();
float mx = 70, my = -15, tmx, tmy;
boolean animating = false;
PFont f;



void setup() {
  size( 800, 400, P3D);
  background(255);
  smooth();
  f = createFont("Arial", 15);
  textMode(SCREEN);
}

void draw() {
  //lights();
  background(255);
  fill(100);
  textFont(f, 15);
  text("drag to orbit", width - 10 - textWidth("drag to orbit"), height -30);
  text("any key to redraw parabola", width - 10 - textWidth("any key to redraw parabola"), height -10);

  //rotate 3d
  translate(width/4, height/2);
  rotateY(radians(mx));
  rotateZ(radians(my));

  // to mark origin and help view 3d
  noFill();
  stroke(100);
  box(20);
  pushMatrix();
  translate(100, 5, -100);
  stroke(200);
  fill(0, 20);
  box(600, 2, 600);
  popMatrix();



  //store y offset
  if (x == initial_x) {
    y_offset = (sq(x)+2*x)/r;
  }

  // stop parabola
  if ( x == initial_x ||  x < -initial_x + 2) {
    x+=2;
    animating = true;
     // add to curve storage
    pts.add(new PVector(x, y));
  }
  else {
    animating = false;
  }

  //calc y
  y = (sq(x)+2*x)/r - y_offset;

  stroke(50, 30, 7);
  noFill();
  strokeWeight(1);

  //draw at origin
  translate(-initial_x, 0);


  //draw curve
  beginShape();
  for (PVector p:pts) {
    curveVertex(p.x, p.y);
  }
  endShape();

  //draw a ball
  if (!animating) {
    translate(pts.get(frameCount%pts.size()).x, pts.get(frameCount%pts.size()).y);
    noStroke();
    fill(220, 190, 35);
    sphere(4);
  }
}
void mousePressed() {
  tmx = mouseX;
  tmy = mouseY;
}
void mouseDragged() {
  mx = tmx - mouseX;
  my = tmy - mouseY;
}

void keyPressed() {
  x = -200;
  pts.clear();
}
v.k.
  • 2,826
  • 2
  • 20
  • 29
0

You're drawing the curves using the curve() command (http://processing.org/reference/curve_.html) which draws a Catmull-Rom spline. In your code, you're only drawing a single spline section (the one between the two control points), so what you're really interested in is "how can I draw only part of a Catmull-Rom spline section". I don't have the answer for that one, but if you change your curve(control1, first, second, control2) call into a bezier(first,c1,c2,second) call (where you will now have to come up with the code for the control points c1 and c2) instead, then you can use de Casteljau's algorithm to cut up a curve into two segments anywhere along it. If you slide up the where-to-cut-it point every frame, and then only draw the first segment that you get from the split operation, it'll look like a curve that draws itself from the start to the end point. See http://pomax.github.io/bezierinfo/#splitting for the description on how to do this (bonus: the source code is even in Processing)

Mike 'Pomax' Kamermans
  • 49,297
  • 16
  • 112
  • 153
0

Make use of the curvePoint() method. Here is a resolution to a similar problem: http://forum.processing.org/one/topic/animation-with-curve.html.

Yuriy
  • 1,384
  • 1
  • 11
  • 17