Transforming Data To Screen Coordinates
Solution 1:
This is how to take your data values and scale them to fit onto the screen. It uses a mapping function to calculate a desired screen value given a specific data value.
function mapRange(value, dataLow, dataHigh, screenLow, screenHigh) {
return screenLow +
(value - dataLow) * (screenHigh - screenLow) / (dataHigh - dataLow);
}
How it works
At its essence, you must scale the incoming data range to fit inside the any range of screen coordinates that are dedicated to displaying the data.
You are scaling one range into another range. You might think of the scaling factor as a percentage of the data range versus the screen range.
// calculate the scaling factor required to fit the data inside the screen
var scalingFactor = screenRange / dataRange;
All data points fall inside the data range which is calculated like this:
// calculate the min/max range of all data
var dataRange= maximumDataValue – minimumDataValue;
All screen coordinates fall inside the screen range which is calculated like this:
// calculate the min/max range of all screen coordinates
// that are dedicated to displaying the data
var screenRange = maximumScreenCoordinateValue – minimumScreenCoordinateValue;
If you want to use the full screen then the screenRange
becomes the screen width.
The next step is to calculate the relative position of a specific data-point inside the full data range:
// calculate any one specified data-point's relative position within
// the full data range
var thisDatumPositionInDataRange = thisDataValue – minimumDataValue;
Finally, use the scalingFactor
to map (==scale) a specific data value onto the available screen coordinate.
// calculate the screen coordinate where the specified dataum
// will be displayed
var screenCoordinate = minimumScreenValue + thisDatumPositionInDataRange * scalingFactor;
In words, this calculation means:
• Start at the minimum (==leftmost) screen coordinate.
• Move righward on the screen by the specified datum’s relative position (in its data range) scaled by the scalingFactor
.
Here's example annotated code:
// supply a data value (value)
// and supply the min & max of the datum and the screen size
// return value mapped to fit onto the screen
function mapRange(value, dataLow, dataHigh, screenLow, screenHigh) {
return screenLow + (screenHigh - screenLow) * (value - dataLow) / (dataHigh - dataLow);
}
// calculate the max & min of a given array
function calcDataMinMax(a){
var min=1000000;
var max=-1000000;
for(var i=0;i<a.length;i++){
var value=a[i];
if(value<min){min=value;}
if(value>max){max=value;}
}
return({min:min,max:max});
}
// Usage:
// example data
var data=[5,10,-3,20,0,2];
// example screen width
var screenWidthMin=0;
var screenWidthMax=640;
// calc the min and max of values in your data
var dataRange=calcDataMinMax(data);
// map the data value 8 to fit onto the screenWidth
var map8=mapRange(8,dataRange.min,dataRange.max,0,100);
Solution 2:
function createTransform(domain, range) {
var domain_min = domain[0];
var domain_max = domain[1];
var range_min = range[0];
var range_max = range[1];
var beta = (range_max / domain_max - range_min / domain_min) * (domain_min * domain_max) / (domain_min - domain_max);
var alpha = (range_min - beta) / domain_min;
return function(x) {
return alpha * x + beta;
};
}
function createTransform(domain, range) {
var domain_min = domain[0];
var domain_max = domain[1];
var range_min = range[0];
var range_max = range[1];
var beta = (range_max / domain_max - range_min / domain_min) * (domain_min * domain_max) / (domain_min - domain_max);
var alpha = (range_min - beta) / domain_min;
return function(x) {
return alpha * x + beta;
};
}
var calculateButton = document.querySelector('.calculate');
var domain_minInput = document.querySelector('.domain_min');
var domain_maxInput = document.querySelector('.domain_max');
var range_minInput = document.querySelector('.range_min');
var range_maxInput = document.querySelector('.range_max');
var xInput = document.querySelector('.x');
var resultBox = document.querySelector('.result');
calculateButton.addEventListener('click', function() {
var domain_min = parseInt(domain_minInput.value);
var domain_max = parseInt(domain_maxInput.value);
var range_min = parseInt(range_minInput.value);
var range_max = parseInt(range_maxInput.value);
var x = parseInt(xInput.value);
var transform = createTransform([domain_min, domain_max], [range_min, range_max]);
resultBox.textContent = transform(x);
});
input {
display: block;
}
domain_min
<input class="domain_min">domain_max
<input class="domain_max">range_min
<input class="range_min">range_max
<input class="range_max">x
<input class="x">
<button class="calculate">Calculate</button>
<h3>result:</h3>
<div class="result"></div>
Post a Comment for "Transforming Data To Screen Coordinates"