Efficient calculation of custom axis position

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
Technicon
Newbie
Newbie
Posts: 43
Joined: Thu Aug 11, 2016 12:00 am
Contact:

Efficient calculation of custom axis position

Post by Technicon » Fri Dec 09, 2016 10:13 am

Hello

I have function "PlaceChartObjects" that automatically calculate the position of custom axis, legend and resize chart margins to prepare place for this elements.
The problem is that I have to call this function and pTChart->Draw() a few times to get proper results because some objects size have wrong width or height after first pass.
This is very inefficient because it is called from ChartAfterDraw event to reflect changes from Chart Editor immediately.

Code: Select all

void __fastcall CBasicChartManager::ChartAfterDraw(TObject *Sender)
{
	if(pTChart)
	{
		ResetAxisPositions();
		ChartTools->PrepareAxisVisibility(pTChart);
		CheckToolsVisibility();
		ChartTools->PlaceChartObjects(pTChart, this);

		TNotifyEvent OnAfterDraw = pTChart->OnAfterDraw;
		try
		{
			pTChart->OnAfterDraw = NULL;
			pTChart->Draw();
			ChartTools->PlaceChartObjects(pTChart, this);
			SetAxisGridVisibility();
			pTChart->Draw();
		}
		__finally
		{
			pTChart->OnAfterDraw = OnAfterDraw;
		}
	}
}
Is there any better way to do this?

Best Regards,
Grzegorz

Yeray
Site Admin
Site Admin
Posts: 9614
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Efficient calculation of custom axis position

Post by Yeray » Mon Dec 12, 2016 10:06 am

Hello Grzegorz,

You could try other events such as OnBeforeDrawChart or OnBeforeDrawSeries to see if they are fired late enough for the elements your calculations depend on to have the appropriate values, and soon enough to avoid needing to repaint it again.
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Technicon
Newbie
Newbie
Posts: 43
Joined: Thu Aug 11, 2016 12:00 am
Contact:

Re: Efficient calculation of custom axis position

Post by Technicon » Thu Jan 05, 2017 9:43 am

Hello

I have also problem when calculation position of titles and legend (CustomPosition = true);
To center eg. title I use Chart->Width to calculate position (center) and i works ok.
But when I try to create metafile to put it on the report like this

Code: Select all

   foMeta->Image1->Picture->Assign(Chart1->TeeCreateMetafile(false, Rect(0, 0, foMeta->Image1->Width, foMeta->Image1->Height)));
the title is not properly center because I need the width of the current draw rect.
How can I read this width from chart?

Best Regards,
Grzegorz

Yeray
Site Admin
Site Admin
Posts: 9614
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Efficient calculation of custom axis position

Post by Yeray » Mon Jan 09, 2017 11:22 am

Hello Grzegorz,

You can read the ChartBounds property. Ie, the width:

Code: Select all

Chart1.ChartBounds.Right-Chart1.ChartBounds.Left
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Technicon
Newbie
Newbie
Posts: 43
Joined: Thu Aug 11, 2016 12:00 am
Contact:

Re: Efficient calculation of custom axis position

Post by Technicon » Mon Jan 09, 2017 12:32 pm

Hello

Thank You for the answer.

I'm still fighting with proper chart objects placement (custom axis axis, title and legend).
I'm calculating position and prepare place for this objects by setting chart margins.

Code: Select all

	
if(Chart->MarginTop != MargTop)
	{
		Chart->MarginTop = MargTop;
	}
	if(Chart->MarginBottom != MargBottom)
	{
		Chart->MarginBottom = MargBottom;
	}
	if(Chart->MarginLeft != MargLeft)
	{
		Chart->MarginLeft = MargLeft;
	}
	if(Chart->MarginRight != MargRight)
	{
		Chart->MarginRight = MargRight;
	}
I don't understand why I have to call a few times chart->Draw() to get right results. I looks like the property I use to calculate position are not properly initialize if I don't call Draw() method.
When I'm changing margin properties eg. MarginBottom do I have to call something to recalculate ChartRect, ChartHeight, ChartWidth etc?


Best Regards,
Grzegorz

Yeray
Site Admin
Site Admin
Posts: 9614
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Efficient calculation of custom axis position

Post by Yeray » Tue Jan 10, 2017 9:27 am

Hello Gregorz,

Some internal properties are calculated at late stages of the drawing process. Ie, the ChartRect (the rectangle defined by the axes) is resized when the legend is drawn, depending on the legend alignment. And some of these internal properties need to have their final values if you want to call functions such as CalcPosPoint/CalcPosValue/CalcSizeValue/... or properties like ChartRect.
That's why we use to recommend forcing a chart repaint before using some properties/methods.

When the only way to achieve something is to play with events manipulating these properties, it may indicate there's something that could be done better by the component or in the customer's code.
To know if there's something the component could do better, we should study the case globally, so a simple example project would probably help here. This is, a project as simple as possible without extra code not needed to demonstrate the situation, but complete enough to be run as-is and to explain the hole problematic.
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Technicon
Newbie
Newbie
Posts: 43
Joined: Thu Aug 11, 2016 12:00 am
Contact:

Re: Efficient calculation of custom axis position

Post by Technicon » Wed Jan 11, 2017 9:32 am

Hello,

I've prepared small project to explain the hole problematic.

When You run application click button "AddBottomSeries"

As You will see You have to click "refresh" button 2x to calculate position of footer sub-footer and bottom legend.

The same problem is to create proper metafile via TeeCreateMetafile You have to create it tree times (3x "Meta" buttons clicks)

I try to call extra draw methods form OnAfterDraw event but the effect is even worse (check cbAutoDraw2x to see the effects).

Chart->ChartHeight which I use to calculate position is still changing values between call Draw().

I use CustomPosition to all my objects (custom axis, legend, title, footer etc.) on the chart to have full control over them but it sill not work as I expect.

Do You have any tips how to properly calculate my objects size to prepare empty place for them and put it on the right position?

Best Regards,
Grzegorz
Attachments
TeeChartTestCase3.zip
Sample project
(100.64 KiB) Downloaded 684 times

Yeray
Site Admin
Site Admin
Posts: 9614
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Efficient calculation of custom axis position

Post by Yeray » Fri Jan 13, 2017 2:18 pm

Hello Grzegorz,

I see the elements moving as you describe, but your project contains more than 1700 lines of code so it isn't easy to debug for us.
Please read StackOverflow's How to create a Minimal, Complete, and Verifiable example as reference.
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Post Reply