65.9K
CodeProject is changing. Read more.
Home

Straight line function, optionally clamped

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.65/5 (5 votes)

Oct 8, 2004

2 min read

viewsIcon

30579

downloadIcon

286

A tiny template for a straight line function with values optionally clamped outside a range

Introduction

Sometimes you just need a simple straight line function, and that's what ClampedLine<class T> gives you. If you feel like getting fancy, you have the option of "clamping" Y to minimum and maximum values outside of a range in X, as shown in the brilliantly detailed picture above. The code is simple, as opposed to fast, and should compile just about anywhere. After you create a ClampedLine, the "function call" T operator()(T X) can be used to pull out a Y value for a particular X.

This certainly isn't original, but I couldn't find a free equivalent anywhere after a quick search.

Here are a couple of examples, rather than rambling on:

#include "clampedline.h"

// Fahrenheit to Celsius conversion.
ClampedLine<float> celsiusFromFahrenheit(32.0, 0, 212.0, 100.0, false);
float y = celsiusFromFahrenheit(72.0); // = 22.2 degrees Celsius

// Clipping and scaling a raw score to produce a "final" score:
// Scale raw 60..90 to final 10..100, 
// values below 60 give 10 and above 90 give 100.
ClampedLine<long>    adjustedScore(60, 10, 90, 100, true);
long finalScore = adjustedScore(-5); // finalScore = 10, the lowest possible
finalScore = adjustedScore(60);      // also gives finalScore = 10
finalScore = adjustedScore(75);      // finalScore = 55, halfway up
finalScore = adjustedScore(90);      // finalScore = 100, the highest possible
finalScore = adjustedScore(140);     // also gives finalScore = 100

Using the code

  1. Include the header file "clampedline.h". Note it doesn't include any other headers.
  2. You'll need two points (X0, Y0) (X1,Y1) on your line. If you specify a clamped line, then values of X below X0 will give a Y value of Y0, and values of X above X1 will return a Y value of Y1.
  3. A simple signed arithmetic type such as long or double works best as the "T" parameter for the template. If you try an unsigned type for T, watch out for values of X that give a nominally negative value of Y.
  4. If your ClampedLine lives a long time, you could package it cleanly in a member function, something like:
    long MyClass::FinalScore(long rawScore)
     {
      static ClampedLine<long>    adjustedScore(
        60, 10, 90, 100, true);
      return adjustedScore(rawScore);
     }
    
  5. The code isn't copyrighted. Scale, offset and clamp to your heart's content, specialize it, add getters and setters. In a brief fit of lucidity I tested this little class before zipping it, but you shouldn't take my word for that.

Points of Interest

When "T" is an integer type, results are rounded (see the code for the standard trick to do that). And you'll get values out without complaint if you have X0 equal to X1 in the constructor for your ClampedLine, just don't expect them to be the values you want:)

History

  • Version 1.0, Oct 7, 2004.