CalcAxisRect replacement

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
Thomas Klingler
Advanced
Posts: 103
Joined: Tue Mar 02, 2004 5:00 am
Location: Bad Wurzach
Contact:

CalcAxisRect replacement

Post by Thomas Klingler » Thu Feb 16, 2006 1:30 pm

Hi,

I just upgraded to Tee Chart Pro 7.06 from the version that came with Delphi 7.

I was using CalcAxisRect to calculate the min and max axis values. This doesn't seem to exist in 7.06. What am I supposed to use instead?

Regards,

Bill

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Thu Feb 16, 2006 3:52 pm

Hi Bill,

You should use axes Minimum and Maximum properties or SetMinMax method:

Chart1.Axes.Left.Minimum
Chart1.Axes.Left.Maximum
Chart1.Axes.Left.SetMinMax(Min,Max)
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

fabnav
Newbie
Newbie
Posts: 8
Joined: Thu Sep 30, 2004 4:00 am
Location: Northern Virginia

Post by fabnav » Tue Feb 21, 2006 7:22 pm

My problem is that I can't call SetMinMax until after there is a valid ChartRect value (because I use ChartRect to detemrine the plot limits), but then after my call to SetMinMax I need the chart to be recreated using my new limits.

For example, if the chart is resized, I need the new size to be placed into ChartRect, then I can call SetMinMax, then I need the chart to be recreated using my limits.

Thanks,

Bill

Pep
Site Admin
Site Admin
Posts: 3303
Joined: Fri Nov 14, 2003 5:00 am
Contact:

Post by Pep » Mon Feb 27, 2006 3:35 pm

Hi Bill,

could you please post the code or a simple sample where I can see how did you use the CalcAxisRect method and give you the equivalent code with the Pro version ?

fabnav
Newbie
Newbie
Posts: 8
Joined: Thu Sep 30, 2004 4:00 am
Location: Northern Virginia

Post by fabnav » Mon Feb 27, 2006 6:55 pm

I have included my code. It has tabs so it doesn't look so good here. The second procedure calls the first one two times. This is very customized for my application, but the main issue I have is that when you turn marks on/off, the axis limits need to be recalculated so that the marks fit on the chart. You don't take marks into account in your code.

My final solution has been to use your source code to add a BeforeCalcAxisRect event, and attach my code to that event. It works just like the old version now.

Regards,

Bill

procedure TCustomChartForm.CalcOneAxis(SelectedAxis: TChartAxis;
SelectedType: TVertAxis);
const
MarkHeight = 18;
Padding = 0.02;
Increment = 0.01;
MaxDouble = 1.0E19;
MinDouble = -1.0E19;
var
ASeries, ArrowMin, ArrowMax, AdjustedChartHeight, SeriesCounter: Integer;
MarksMin, MarksMax, ChartMin, ChartMax, SeriesMin, SeriesMax, Pad, NewTop,
NewBottom, MarksInc: Double;
HaveBarSeries, IsBarSeries: Boolean;
Diff, MaxSteps, LogVal, StepSize, MaxIncrement, UPL, LPL: Double;
begin
with CustomChart do
begin
{ Initialize variables }
MarksMin := MaxDouble;
MarksMax := MinDouble;
ChartMin := MaxDouble;
ChartMax := MinDouble;
ArrowMin := 0;
ArrowMax := 0;
SeriesCounter := 0;
HaveBarSeries := False;
{ Scan active selected axis series and get min and max values }
for ASeries := Pred(SeriesCount) downto 0 do
with Series[ASeries] do
{ Use the series if it is active and if it is for the selected axis, or if
merge limits is set }
if Active and ((VertAxis = SelectedType) or FUseMergedLimits) then
begin
{ Count the number of series using the selected axis }
Inc(SeriesCounter);
{ Determine if one of the series for the selected axis is a bar series }
IsBarSeries := Series[ASeries] is TBarSeries;
if IsBarSeries then
HaveBarSeries := True;
{ Calculate axis max and min values }
SeriesMax := MaxYValue;
SeriesMin := MinYValue;
{ Do not use the series limits if they are both zero, unless this is a
target series }
if (SeriesMax <> 0.0) or (SeriesMin <> 0.0) or
(Series[ASeries].Title = 'Target') then
begin
if SeriesMax > ChartMax then
ChartMax := SeriesMax;
if SeriesMin < ChartMin then
ChartMin := SeriesMin;
end;
if Marks.Visible then
begin
if SeriesMax > MarksMax then
begin
MarksMax := SeriesMax;
ArrowMax := Marks.ArrowLength;
end;
if IsBarSeries and (SeriesMin < 0) and (SeriesMin < MarksMin) then
begin
MarksMin := SeriesMin;
ArrowMin := Marks.ArrowLength;
end;
end;
end;

{ Exit if there are no active series using the selected axis }
if SeriesCounter = 0 then
Exit;

{ Set both chart axis to zero if they have not ever been assigned }
if (ChartMin = MaxDouble) and (ChartMax = MinDouble) then
begin
ChartMax := 0.0;
ChartMin := 0.0;
end;
{ Setup bottom axis start and end positions }
with BottomAxis do
begin
if HaveBarSeries then
begin
StartPosition := 2;
EndPosition := 98;
end
else
begin
StartPosition := 4;
EndPosition := 96;
end;
end;
{ Bar charts always are zero based }
if (HaveBarSeries or FZeroBased) and (ChartMin > 0) then
ChartMin := 0.0;
{ Calculate the chart height }
AdjustedChartHeight := Max(MinChartHeight,
ChartRect.Bottom - ChartRect.Top - BottomAxis.MaxLabelsWidth);
if ChartMax <> ChartMin then
begin
{ Adjust for marks }
MarksInc := Abs(Increment * (ChartMax - ChartMin));
NewTop := (MarkHeight + ArrowMax) / AdjustedChartHeight;
if MarksMax > MinDouble then
while (ChartMax - MarksMax) / (ChartMax - ChartMin) <= NewTop do
ChartMax := ChartMax + MarksInc;
NewBottom := 1.0 - (MarkHeight + ArrowMin + 2) / AdjustedChartHeight;
if (MarksMin <> 0) and (MarksMin < MaxDouble) then
while (ChartMax - MarksMin) / (ChartMax - ChartMin) >= NewBottom do
begin
ChartMin := ChartMin - MarksInc;
while (ChartMax - MarksMax) / (ChartMax - ChartMin) <= NewTop do
ChartMax := ChartMax + MarksInc;
end;
end;

{ Retain the previous limits if user plot limits or use last limits is set }
if ((FUserPlotLimitsLeft or FUseLastLimitsLeft) and (SelectedType = ALeftAxis)) or
((FUserPlotLimitsRight or FUseLastLimitsRight) and (SelectedType = ARightAxis)) then
begin
ChartMax := SelectedAxis.Maximum;
ChartMin := SelectedAxis.Minimum;
end
else
begin
{ Add padding to limits }
Pad := Padding * (ChartMax - ChartMin);
if Pad > 0.0 then
begin
{ Apply padding to the chart maximum }
ChartMax := ChartMax + Pad;
{ Apply padding to the chart minimum if the minimun is negative }
if ChartMin < 0.0 then
ChartMin := ChartMin - Pad;
end;
end;
{ Calculate difference in values }
Diff := ChartMax - ChartMin;
{ Check for single value }
if Diff < 0.0001 then
begin
ChartMax := ChartMax + Abs(Padding * ChartMax);
ChartMin := ChartMin - Abs(Padding * ChartMax);
{ Check for zero value }
if ChartMax = 0.0 then
begin
ChartMax := 1.0;
ChartMin := 0.0;
end;
{ Recalculate difference }
Diff := ChartMax - ChartMin;
end;
{ Calculate log of difference }
LogVal := Log10(Diff);
if LogVal < 0 then
LogVal := LogVal - 1.0;
{ Calculate max increment }
MaxIncrement := Power(10.0, Trunc(LogVal));
{ Calc max steps }
MaxSteps := Diff / MaxIncrement;
{ Reduce increment if possible }
StepSize := MaxIncrement;
{ Max will be 12 steps }
if MaxSteps <= 1.2 then
StepSize := MaxIncrement / 10.0
else
if MaxSteps <= 2.4 then
StepSize := MaxIncrement / 5.0
else
if MaxSteps <= 6.0 then
StepSize := MaxIncrement / 2.0;
{ Minimum step size for integer series, or a bar series of unknown type, is 1.0 }
if (StepSize < 1.0) and ((SelectedAxis.DateTimeFormat = 'I') or
(HaveBarSeries and (SelectedAxis.DateTimeFormat = ''))) then
StepSize := 1.0;
{ Calc UPL }
UPL := StepSize * Round(ChartMax / StepSize);
if UPL < ChartMax then
UPL := UPL + StepSize;
LPL := UPL;
{ Calculate the LPL }
while LPL > ChartMin do
LPL := LPL - StepSize;
{ Set axis values }
with SelectedAxis do
begin
RoundFirstLabel := False;
Increment := StepSize;
SetMinMax(LPL, UPL);
end;
end;
end;

procedure TCustomChartForm.CustomChartBeforeCalcAxisRect(Sender: TObject);
var
ASeries, AdjustedChartHeight: Integer;
begin
with CustomChart do
begin
{ Exit if zoomed or in design state }
if Zoomed or (csDesigning in ComponentState) then
Exit;
{ Call inherited and exit if there is an active gantt series }
for ASeries := Pred(SeriesCount) downto 0 do
if Series[ASeries].Active and (Series[ASeries] is TGanttSeries) then
begin
{ Automatically calculate the bottom axis labels size }
BottomAxis.LabelsSize := 0;
Exit;
end;
AdjustedChartHeight :=
ChartRect.Bottom - ChartRect.Top - BottomAxis.MaxLabelsWidth;
{ If the height allocated for the chart is less than the minimum, set the
labels size to allow for the minimum chart height }
if AdjustedChartHeight < MinChartHeight then
BottomAxis.LabelsSize := ChartRect.Bottom - ChartRect.Top - MinChartHeight
else // Auto calculate the labels size
if BottomAxis.LabelsFont.Size = 8 then
BottomAxis.LabelsSize := BottomAxis.MaxLabelsWidth + 5
else
BottomAxis.LabelsSize := 0;
{ Do the right axis first }
CalcOneAxis(RightAxis, ARightAxis);
{ Do the left axis last }
CalcOneAxis(LeftAxis, ALeftAxis);
end;
end;

Post Reply