Search code examples
mathlogarithm

Convert linear scale to logarithmic scale


I'm taking data from a plot of a 2D line drawing and trying to plot it on a piece of paper of a given size. (The paper size can change) To make the line drawings fit on the paper, I need to scale it. Unfortunately, some of the legs on this plot are very short, and some are extremely long, so a simply linear scale results in areas too small to see with a single line often taking up half the paper. I'm trying to use logarithmic scaling to compensate for this, so the entire drawing is on the piece of paper and the longest lengths are attenuated more than the shortest lengths. I just can't seem to wrap my head around the math here. If I can understand the math, I can translate that into the C++ code I need.

I've looked here: Convert Linear scale to Logarithmic
And here: https://math.stackexchange.com/questions/970094/convert-a-linear-scale-to-a-logarithmic-scale

The basics:
I need to convert linear x,y values into logarithmic values ranging from 1-paperWidth and from 1-paperHeight.
My x and y values will always be positive and will range from x-min to x-max, and y-min to y-max.

Can someone dumb down this math for me?
I would REALLY appreciate it!


Solution

  • Let you have range xmin..xmax and want to map it logaritmically onto canvas coordinates X0..X1. Equation is:

    X = a + b * ln (x)
    

    You can use decimal logarithm log10 if you want (this change just scales b coefficient)

    Substitute start and end points:

    X0 = a + b * ln(xmin)
    X1 = a + b * ln(xmax)
    

    To find a and b parameters, you need to solve equation system above. Subtract the first equation from the second one

    X1 - X0 = b *(ln(xmax) - ln(xmin))  = b * ln(xmax / xmin) 
    so
    b = (X1 - X0) / ln(xmax / xmin)
    

    Now put this b value in the first equation to get a

    a = X0 - b * ln(xmin)
    

    Example:

    xmin = 0.01
    xmax = 100
    X0 = 20
    X1 = 800
    b = (X1 - X0) / ln(xmax / xmin) = 780/9.21 = 84.7
    a = 20 - 84.7 * (-4.6)= 410
    

    So transformation is:

    X = 410 + 84.7 * ln(x)
    

    Check for some intermediate points (should be evenly spaced in logaritmic space):

    x = 0.01 => X = 20
    x = 0.1 =>  X = 215
    x = 1  =>   X = 410    (OK, this is (20+800)/2)
    x = 10 =>   X = 605
    x = 100 =>  X = 800
    

    Concerning question in comments:

    Logarithmic function y=ln(x) transforms range x1..x2 (length x2-x1) into range of length ln(x2)-ln(x1).
    But if we want to have specific result range length (for example, canvas size for drawing), we should introduce scale coefficient b.
    If we want that result range starts from specific value (for example, canvas coordinates start from 0), we should introduce shift coefficient a.

    So we make linear transformation of result into needed range.