Change your scales

Written by kevpluck | Published 2017/04/24
Tech Story Tags: programming | climate-change | global-warming | animation | tutorial

TLDRvia the TL;DR App

This is part 7 of an N part series detailing how I make my animations.

Prev Next

Now we have reached the limits of what we can display in our 500x500 animation so we will need to change the scale to fit the plot for the full 58 years of data.

So once x is greater than 500 we can start reducing the x scale along with the y. Let’s do that:

float xScale = 1.0;  
float yScale = 40.0;  
  
if(frameCount > width)  
{  
  xScale = float(width) / float(frameCount);  
}  
  
float x = frameCount \* xScale;  
float y = (co2 - 313.04) \* yScale;  
  
ellipse(x, height - y, 1, 1);

What’s with the float()? Because width and framcCount are integers when you divide them the result is an integer. Unfortunately 500/501 as an integer results in 0, not 0.998 so we have to convert the integer values into floats. You’ll also note that when I am using a constant value, like 40.0 I include the decimal point, this causes the computer to do floating point arithmetic and not integer arithmetic. For example the result of 1/10 would equal 0 while the result of 1.0/10.0 would be 0.1 as expected. Be aware that 1.0/10 would also result in 0!

Huh? Oh, I forgot to clear the frame for each draw!

Simply add background(0); to the first line of draw(). Now we get:

Lovely. Now let’s do the same to the y axis.

This’ll be a tad different as the y value doesn’t increase linearly so we’ll keep a running maximum value and scale according to that. As we already multiply our y-axis by 40 already it naturally leads to us setting:

float yScale = 40.0;

Place that line just before the void draw() definition so that yScale is remembered between draw() executions.

Now each time we calculate a new y value we need to check if this exceeds the previous height value, if so then calculate the new yScale:

if(y * yScale > height){yScale = float(height)/y;}

Resulting in:

Here’s the entire code:

import java.time.*;

FloatDict _data = new FloatDict();LocalDate _startDate = LocalDate.of(1958, 3, 29);

void setup(){loadData();size(500,500);background(0);stroke(255,255,0);}

float yScale = 40.0;

void draw(){background(0);float xScale = 1.0;

if(frameCount > width){xScale = float(width) / float(frameCount);}

for(int dataIndex = 1; dataIndex <= frameCount; dataIndex++){int daysFromStart = (dataIndex - 1) * 7;LocalDate frameDate = _startDate.plusDays(daysFromStart);

if(\_data.hasKey(frameDate.toString()))  
{  
  float co2 = \_data.get(frameDate.toString());  
          
  float x = dataIndex;  
  float y = (co2 - 313.04) ;  
    
  if(y \* yScale > height)   
  {  
    yScale = float(height)/y;  
  }  
    
  ellipse(x \* xScale, height - (y \* yScale), 1, 1);  
}  

}}

void loadData(){String[] lines = loadStrings("weekly_in_situ_co2_mlo.csv");

for (String line : lines){if( line.startsWith("\"") ) continue;

String\[\] values = split(line, ',');  
String date = values\[0\];  
float co2 = parseFloat(values\[1\]);  
\_data.set(date, co2);  

}}

Join me next week when we play with speed and add some text and axis and stuff…

Edit: When I first published this I had a more complicated way of calculating yScale, this is now simpler.


Published by HackerNoon on 2017/04/24