More on vector fields – surfaces

by tsulej

Recently I’ve found one more nice method for vector fields visualization. What is a vector field and how to visualize it you can find in my previous posts:

Now let’s introduce new concept based on vectors’ angles. Angle can be calculated easily using atan2() function.

So let’s define:

\beta=atan2(f(\vec{v})) or \beta=atan2(f(\vec{v})-\vec{v})

where \vec{v} is input vector and f() is vector field function ie. \mathbf{R}^{2} to \mathbf{R}^{2} function.

Having that \alpha and \beta are from the range [-\pi,\pi] we can scan vector field, calculate angles and draw points. It will be kind of heat map of all possible pairs of angles given vector field can generate.

Let’s see how the code looks like:

void setup() {
  size(800, 800);
  fill(10, 10);

void draw() {
  for (int i=0; i<10000; i++) { // draw 10000 points at once
    PVector v = new PVector(random(-1, 1), random(-1, 1)); // random input vector
    PVector fv = popcorn(v); // vector field
    //fv.sub(v); // subtract trick

    float alpha = v.heading();
    float beta = fv.heading();

    float x = map(alpha, -PI, PI, 50, width-50);
    float y = map(beta, -PI, PI, 50, height-50);

    rect(x, y, 1, 1);

void keyPressed() {
  if (keyCode == 32) saveFrame("######.jpg");

float popcorn_c = random(-0.8, 0.8);
float popcorn_f = random(-0.8, 0.8);

PVector popcorn(PVector p) {
  float x = p.x + popcorn_c * sin(tan(3.0 * p.y));
  float y = p.y + popcorn_f * sin(tan(3.0 * p.x));
  return new PVector(x, y);

Result of the code on vector field called popcorn.


To get different variety let’s uncomment line 13 to use difference of vector field result and input.


Lovely, what about another vector field – waves?

float waves_b = random(-0.8, 0.8);
float waves_e = random(-0.8, 0.8);
float waves_c = random(-0.8, 0.8);
float waves_f = random(-0.8, 0.8);

PVector waves(PVector p) {
  float x = p.x + waves_b * sin(p.y * (1.0 / (waves_c * waves_c) ));
  float y = p.y + waves_e * sin(p.x * (1.0 / (waves_f * waves_f) ));

  return new PVector(x, y);


I called result as surfaces since somtimes it looks like 3d surface folded in the space.

What can be done more here?

Add noise

Let’s add some distortion to our angles based on noise function. This will break too much symmetry in the image.

Replace draw() with new one:

void draw() {
  for (int i=0; i<50000; i++) {
    PVector v = new PVector(random(-1, 1), random(-1, 1));
    PVector fv = waves(popcorn(v));

    float alpha = v.heading();
    float beta = fv.heading();

    float nalpha = 0.5 * (noise(v.x,fv.y,alpha)-0.5);
    float nbeta = 0.5 * (noise(fv.x,v.y,beta)-0.5);

    float x = map(alpha+nalpha, -PI, PI, 50, width-50);
    float y = map(beta+nbeta, -PI, PI, 50, height-50);

    rect(x, y, 1, 1);

And results!


Two vector fields

You can of course use two vector fields and calculate \alpha from a vector field not from input vector.

Color and log-density rendering

Using different rendering method (log-density) and color taken from vector magnitude we can achive following results.

More can be seen on folds2d site