Page 1 of 1

Help aligning top and bottom axes

Posted: Wed Feb 04, 2004 11:28 pm
by 9078925
I'm trying to align the top axis labels with the bottom and round it off as well. I was able to align them using the OnGetAxisLabel and OnGetNextAxisLabel, but now I'm trying to adjust the top scale so it fits nicely(labels are rounded off). I need to do this before the axis events. What I really would like to know is the logic Steema uses to determine where to put labels, ie. the interval between the max and first label and each subsequent label. Can anyone help?

Posted: Fri Feb 06, 2004 2:50 pm
by Chris
Hi Craig,
I'm trying to align the top axis labels with the bottom and round it off as well. I was able to align them using the OnGetAxisLabel and OnGetNextAxisLabel, but now I'm trying to adjust the top scale so it fits nicely(labels are rounded off). I need to do this before the axis events. What I really would like to know is the logic Steema uses to determine where to put labels, ie. the interval between the max and first label and each subsequent label. Can anyone help?
It will be a pleasure!

Could you please send me a VB (or whatever) project that I can run "as is" here to show me where you've got to with this? You could post it to news://www.berneda.com/steema.public.attachments

Posted: Mon Feb 09, 2004 10:29 pm
by 9078925
Hi Chris,

I figure it would be too complicated to attach the project since it is rather large and relies on many other files to get data, etc. So I'm hoping you can at least help with some of the general logic. I'll describe what I've done so far:

Here are my axis events:

Code: Select all

void CWFGraphDlg::OnBeforeDrawAxesTchart1()
{
	_Count = 0;
	_Increment1Percentage = 0;
	_Increment2Percentage = 0;
}

void CWFGraphDlg::OnGetAxisLabelTchart1(long Axis, long SeriesIndex, long ValueIndex, BSTR* LabelText)
{
	// To line up the top axis, we need to first get the bottom axis increments
	// When labels are rounded off, the increment between the first label and max point is different
	// than the rest(while automatic), hence _Increment1 and _Increment2
	// 1st time called, LabelText is maximum, 2nd is minimum, 3rd is the first auto generated label below max

	if ( _SyncAxes )
	{
		if ( Axis == atBottom )
		{
			double max = m_Chart1.GetAxis().GetBottom().GetMaximum();
			double min = m_Chart1.GetAxis().GetBottom().GetMinimum();	
			
			if ( (max != min) && (max > 0.00000001) ) // if you retrieve max of 0, it's not exactly 0
			{
				_Count++;
				CString labelText = *LabelText;
				labelText.Remove(',');
				if ( _Count == 3 ) 
				{
					_FirstLabel = atof(labelText);
					_Increment1Percentage = (max - _FirstLabel) / (max-min);
				}
				if ( _Count == 4 )
                    _Increment2Percentage = (_FirstLabel - atof(labelText)) / (max-min);
			}			
		}
	}
}

void CWFGraphDlg::OnGetNextAxisLabelTchart1(long Axis, long LabelIndex, double* LabelValue, BOOL* MoreLabels)
{
	// This function allows us to manually set each label, it is called after OnGetAxisLabel
	// It will be called as long as MoreLabels = true and LabelValue > min

	if ( _SyncAxes )
	{
		if ( Axis == atTop )
		{		
			double max = m_Chart1.GetAxis().GetTop().GetMaximum();
			double min = m_Chart1.GetAxis().GetTop().GetMinimum();

			// if you retrieve max of 0, it's not exactly 0
			if ( (max != min) && (max > 0.00000001) && (_Increment2Percentage != 0) ) 
			{
				*MoreLabels = true;
				if ( LabelIndex == 0 ) // The first label is max - increment1
				{
					*LabelValue = max - (_Increment1Percentage*(max-min));
					_FirstLabel = *LabelValue;
				}
				else // Every other label is previous label - increment2
				{
					*LabelValue = _FirstLabel - (_Increment2Percentage*(max-min));				
					_FirstLabel = *LabelValue;
				}	

			}

		}
	}
}
Now, in my main graph function, I want to determine the max/min for top axis so the labels fall on more even numbers. Here's the logic I've tried first:

1. Determine a suitable increment based on range of top axis
2. Round off the max/min for both axes to nearest decimal
3. Increase the top axis by increment until it is equally divisable by or into bottom axis.

This actually works most of the time, but not if the difference between top and bottom scales is very large, or some other factors, I don't know.

Then I tried determining the top and bottom intervals, based on 1, 2 or 5, and the number of intervals. Then increasing the top axis until it's number of intervals is equally divisable by bottom number. Then make sure the remaining percentage is the same for top and bottom. This also works, almost, but doesn't round off very nice and sometimes get infinite loops because of the precision I have to use.

So this is where I'm stuck, any suggestions would be helpful. Thank you

Posted: Wed Feb 11, 2004 3:30 pm
by Chris
Hi --
So this is where I'm stuck, any suggestions would be helpful. Thank you
Mmm, well, these routines are going to depend, to some extent, on the type of data being fed into each series.

I've had a go at a similar problem and came up with the following solution (please excuse the VB code, but the TeeChart AXv6 objects and members are identical):

Code: Select all

Private Sub Form_Load()
With TChart1
    .Aspect.View3D = False
    .AddSeries scLine
    
    For i = 0 To 90000 Step 10000
        .Series(0).AddXY i, Rnd * 100, "", clTeeColor
    Next i
    
    .AddSeries scLine
    For i = 0 To 17
        .Series(1).AddXY i, Rnd * 100, "", clTeeColor
    Next i
    .Series(1).HorizontalAxis = aTopAxis
    
    .Environment.InternalRepaint
    BAxisMax = .Axis.Bottom.Maximum
    BAxisMin = .Axis.Bottom.Minimum
    BAxisRange = BAxisMax - BAxisMin
    BAxisIncrement = .Axis.Bottom.CalcIncrement
    BAxisNoLabels = BAxisRange / BAxisIncrement
    
    TAxisMax = .Axis.Top.Maximum
    TAxisMin = .Axis.Top.Minimum
    TAxisRange = TAxisMax - TAxisMin
    TAxisIncrement = TAxisRange / BAxisNoLabels
    
    .Axis.Top.Increment = TAxisIncrement
    
End With
End Sub
Please tell me what problems you see with the above proposed solution

Posted: Wed Feb 11, 2004 10:21 pm
by 9078925
Chris,

That won't work. In your example, the top axis increment would be 1.888888, that doesn't look like a nice label to me :D

The whole top range needs to be expanded until the number of bottom increments fits evenly into the top, or vice versa.

I still haven't been able to get it yet, I'm about to give up. Although, I wish I new about the .InternalRepaint and .CalcIncrement sooner, that certainly makes things easier!

Let me know if you have any other ideas.

Thanks.

Posted: Thu Feb 12, 2004 9:20 am
by Chris
Hi --
The whole top range needs to be expanded until the number of bottom increments fits evenly into the top, or vice versa.
OK, then try running the code below:

Code: Select all

Dim BAxisRange, TAxisRange, BAxisIncrement, TBAxisIncrement, mCount

Private Sub Command1_Click()
With TChart1
    .Axis.Top.Increment = TAxisRange / mCount
    .Axis.Bottom.Increment = BAxisRange / mCount
End With
mCount = mCount + 1
End Sub

Private Sub Form_Load()
mCount = 2
With TChart1
    .Aspect.View3D = False
    .AddSeries scLine
    
    For i = 0 To 90000 Step 10000
        .Series(0).AddXY i, Rnd * 100, "", clTeeColor
    Next i
    
    .AddSeries scLine
    For i = 0 To 17
        .Series(1).AddXY i, Rnd * 100, "", clTeeColor
    Next i
    .Series(1).HorizontalAxis = aTopAxis
    
    .Environment.InternalRepaint

    BAxisMax = .Axis.Bottom.Maximum
    BAxisMin = .Axis.Bottom.Minimum
    BAxisRange = BAxisMax - BAxisMin
    BAxisIncrement = .Axis.Bottom.CalcIncrement
    BAxisNoLabels = BAxisRange / BAxisIncrement

    TAxisMax = .Axis.Top.Maximum
    TAxisMin = .Axis.Top.Minimum
    TAxisRange = TAxisMax - TAxisMin
    TAxisIncrement = .Axis.Top.CalcIncrement
    TAxisNoLabels = TAxisRange / TAxisIncrement
End With
End Sub
I guess that when mCount = 4 you have "nice" labels -- it's then a case specifying a conditional that defines the label increment you would like to see while stepping through the above logic.

Posted: Fri Feb 13, 2004 11:45 pm
by 9078925
Sorry Chris, that won't work either. The answer is not to change the increment, but the max/min values so the top scale will fit evenly into the bottom.

Actually, I found a solution. Here's what I do:
- Round off both max/min top and bottom to nearest increment.
- Increase the top range by an amount that makes its' number of increments equally divisible by or into the bottom number of increments.
- Let my axis events handle the rest.

It was just a matter of getting that second calculation correct.

Thanks for your help.