Search code examples
delphiteechartdelphi-10-seattle

Is an exponential scale of an axis with TDBChart possible?


Is it possible to have an exponential scale of an axis with TDBChart (instead of a logarithmic scale)?

A logarithmic scale of the y-axis is useful, when the graph corresponds to an exponential growth. As the following example shows, the y-axis values of the graph between 0 and 1 are extra highlighted while indiviual outliers beyond that will become more and more unimportant:

However, if there is somekind of an inverse behavior of a graph compared to above example, where small values aren't very important (noise) but indiviual outliers should be made explicitly visible, then an exponential scale is useful:

So, is it possible to scale an axis with TDBChart exponentially?


Solution

  • The following code populates a series with exponential data:

    uses Series, Math;
    
    procedure TForm1.FormCreate(Sender: TObject);
    var i: Integer;
    begin
      Chart1.View3D:=False;
      Chart1.Legend.Visible:=false;
    
      with Chart1.AddSeries(TLineSeries) as TLineSeries do
      begin
        Pointer.Visible:=true;
        Pointer.Size:=2;
    
        for i := 1 to 10 do
          Add(Power(2, i));
      end;
    end;
    

    The result looks as follows:

    exponential growth


    Then, if you add the following code to the above:

      Chart1.Axes.Left.Logarithmic:=true;
    

    Now the data is still the same but the left axis scale changes to a logarithmic scale:

    logarithmic scale


    You can also change the labels format, ie:

      Chart1.Axes.Left.AxisValuesFormat:='00e-0';
      Chart1.Axes.Left.LabelsExponent:=true;
    

    exponential labels


    Edit:

    Setting a logarithmic base of 1.544 on TeeChart and custom labels to show those labels in your screenshot:

    uses Series, Math;
    
    procedure TForm1.FormCreate(Sender: TObject);
    var i: Integer;
    begin
      Chart1.View3D:=False;
      Chart1.Legend.Visible:=false;
    
      with Chart1.AddSeries(TLineSeries) as TLineSeries do
      begin
        Pointer.Visible:=true;
        Pointer.Size:=2;
    
        for i := 1 to 7 do
          Add(Power(2, i));
      end;
    
      with Chart1.Axes.Left do
      begin
        Logarithmic:=True;
        LogarithmicBase:=1.544;
        MinorTicks.Visible:=false;
    
        with Items do
        begin
          Clear;
          Add(0.1, '0.1');
          Add(1.2, '1.2');
          Add(1.5, '1.5');
          Add(2, '2');
          Add(3, '3');
          Add(5, '5');
          Add(7, '7');
          Add(10, '10');
          Add(15, '15');
          Add(20, '20');
          Add(30, '30');
          Add(40, '40');
          Add(50, '50');
          Add(70, '70');
          Add(100, '100');
    
          SetMinMax(0.1, 100);
        end;
      end;
    end;
    

    It looks like this:

    LogarithmicBase 1.544

    The distance between 0.1 and 1.2 is much greater than in your screenshot, and I'm not sure if that's a bug or if that's mathematically correct.
    I can change the axis scale to start at 1 instead of 0.1 to make it look much similar to your screenshot but I'm not sure if that would be what you want:

          SetMinMax(1, 100);
    

    Axis Minimum 1)