Dynamic LinePen

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
ix07
Newbie
Newbie
Posts: 11
Joined: Wed Apr 15, 2015 12:00 am

Dynamic LinePen

Post by ix07 » Wed May 20, 2015 4:57 pm

Hi.

I am using TLineSeries to display a series of X/Y values. My customer wants the LineStyle for the connecting lines between values for all x-values below a certain threshold value to be drawn in the "dotted" style.

In my first attempts I tried to "misuse" the "OnGetPointerStyle" event like this:

Code: Select all

Teengine::TSeriesPointerStyle __fastcall ResultDiagramCompositeView::OnGetPointerStyle(Teengine::TChartSeries* sender, int valueIndex)
{
   TSeriesPointerStyle pointerStyle = TSeriesPointerStyle::psCircle;

   if(TLineSeries* const lineSeries = dynamic_cast<TLineSeries*>(sender))
   {
      double n = lineSeries->XValues->Items[valueIndex];
      if(n >= 1.5)
      {
         lineSeries->LinePen->Style = psSolid;
      }
      else
         lineSeries->LinePen->Style = psDot;
   }

   return pointerStyle;
}
However this is far from optimal because not always are there points near the threshold value (currently I generate some via interpolation) and the LineStyle changes when I move the mosue cursor over the diagram (redraw problems).

Is there a way to achieve this in a clean way?

Thanks a lot!

Best Regards
Eike Petersen

P.S: I am using TeeChart Pro 2015 VCL with C++ Builder XE7

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

Re: Dynamic LinePen

Post by Yeray » Thu May 21, 2015 2:39 pm

Hello,

Here it is a similar question discussed. It's on Java but the same applies here:
http://www.teechart.net/support/viewtop ... 86&p=59469

FYI, here it is an improved version of the Interpolation algorithm:
http://www.teechart.net/support/viewtop ... 220#p68220

If you still find problems with it, don't hesitate to let us know.
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

ix07
Newbie
Newbie
Posts: 11
Joined: Wed Apr 15, 2015 12:00 am

Re: Dynamic LinePen

Post by ix07 » Fri May 22, 2015 3:43 pm

Uhm. I'm not sure that's the same problem. I need to change the LineStyle (psSolid, psDash etc.) - not the color. Or did I miss something? Can you provide me with a actual example (Delphi or C++) in which you change the line style for each x/y value?

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

Re: Dynamic LinePen

Post by Yeray » Tue May 26, 2015 11:44 am

Hello,

Take a look at the attached Delphi example:
testInterpolation.zip
(3.03 KiB) Downloaded 606 times
I'm calculating the interpolation XValues (interpPoints) for a given YValue (determined by the colorLine) and adding them to a secondary series (interpLine). Then, maintaining this series I can hide the original series (sourceLine).

This is how it looks:
interpolated.png
interpolated.png (33.56 KiB) Viewed 16240 times
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

ix07
Newbie
Newbie
Posts: 11
Joined: Wed Apr 15, 2015 12:00 am

Re: Dynamic LinePen

Post by ix07 » Tue May 26, 2015 2:15 pm

Hi Yeray.

Thank you for your example. In your example you are using 'GetPointerStyle' too (as I do), and unfortunately you do not change the LineStyle in that example.

Here is my current code:

-- snip --

Code: Select all

Teengine::TSeriesPointerStyle __fastcall ResultDiagramCompositeView::OnGetPointerStyle(Teengine::TChartSeries* sender, int valueIndex)
{
   TSeriesPointerStyle pointerStyle = TSeriesPointerStyle::psNothing;

   if(TLineSeries* const lineSeries = dynamic_cast<TLineSeries*>(sender))
   {
      lineSeries->LinePen->Style = psDot;

      if(valueIndex > 0)
      {
         double n = lineSeries->XValues->Items[valueIndex];
         if(n >= 1.5)
         {
            lineSeries->LinePen->Style = psSolid;
         }
      }
   }

   return pointerStyle;
}
-- snap --

This works, but there seems to be a refresh problem. It is drawn correctly the first time, but if you move the mouse cursor over the diagram window the 'dotted' style disappears.

I attached two screenshots to illustrate that.

I am using the latest version of TeeChart 2015 Pro for VCL.
Attachments
ss2.jpg
Screenshot after mouse after window
ss2.jpg (148.36 KiB) Viewed 16243 times
ss1.jpg
Screenshot before mouse over window
ss1.jpg (147.94 KiB) Viewed 16232 times

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

Re: Dynamic LinePen

Post by Yeray » Wed May 27, 2015 8:17 am

Hello,

I see I have misread the initial post. The example I did was considering a threshold given by an horizontal line (an Y value) so I was calculating all the points crossing that line. Besides, I was changing the line color instead of the style.

To consider a threshold given by a vertical line (an X value) - since we are talking about a regular line series, and not a THorizLineSeries - we only have to calculate one crossing point. This part would be a simpler than what I did in that example.

To change the line style instead of changing the line color you should do it at OnGetPointerStyle. Changing the color of the line/pointer can be done through the according arrays but there isn't an array in the series to determine the line style; there's a unique LinePen.Style property in the series, so you should use the OnGetPointerStyle to change that series property depending on the valueindex being drawn.
Here note when OnGetPointerStyle is fired for a ValueIndex the line segment from ValueIndex-1 to ValueIndex+1 has been already drawn. So, at the time OnGetPointerStyle is fired you should interrogate XValue[ValueIndex+1] to set the series LinePen.Style for the next segment that will be drawn.
With this trick, the only question open is what happens with the first segment; how to set the according LinePen.Style for the first segment? You can use OnBeforeDrawSeries for that.

It would be something like this:

Code: Select all

const threshold = 1.5;

function TForm1.LineGetPointerStyle(Sender:TChartSeries; ValueIndex:Integer): TSeriesPointerStyle;
begin
  lineSeries.LinePen.Style:=psSolid;

  if (ValueIndex+1>-1) and (ValueIndex+1<Sender.Count) then
  begin
    if Sender.XValue[ValueIndex+1] < threshold then
      lineSeries.LinePen.Style:=psDot;
  end;
end;

procedure TForm1.BeforeDrawSeries(Sender: TObject);
begin
  if (lineSeries<>nil) and (lineSeries.Count>0) and (lineSeries.XValue[0] < threshold) then
    interpLine.LinePen.Style:=psDot
  else
    interpLine.LinePen.Style:=psSolid;
end;
So, your code snipped looks fine to me. I'd only change valueIndex for valueIndex+1 at OnGetPointerStyle and use BeforeDrawSeries as above.

If you still find problems with it, don't hesitate to let us know and keep in mind a simple example project we can run as-is would help us to reproduce the situation and try to find a more concrete solution for you.
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

ix07
Newbie
Newbie
Posts: 11
Joined: Wed Apr 15, 2015 12:00 am

Re: Dynamic LinePen

Post by ix07 » Wed May 27, 2015 10:37 am

Sigh. I appreciate your efforts, but did you read my last posting? I have everything working *except* that the changed "LineStyle" reverts when you move the mouse cursor over the diagram window (you don't even have to click or interact, just moving the cursor is enough). I even posted two screenshots where you can see that in one picture the line series have a first segment with the "dot" line style and a second picture in which the line style is solid again. This seems to be a refresh problem. As soon as the mouse cursor enters the diagram any manipulation of the line style in "OnGetPointerStyle" is discarded.

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

Re: Dynamic LinePen

Post by Yeray » Wed May 27, 2015 12:21 pm

Hello,
ix07 wrote:Sigh. I appreciate your efforts, but did you read my last posting? I have everything working *except* that the changed "LineStyle" reverts when you move the mouse cursor over the diagram window (you don't even have to click or interact, just moving the cursor is enough). I even posted two screenshots where you can see that in one picture the line series have a first segment with the "dot" line style and a second picture in which the line style is solid again. This seems to be a refresh problem. As soon as the mouse cursor enters the diagram any manipulation of the line style in "OnGetPointerStyle" is discarded.
I'm sorry, I was trying to explain the theory of the solution. I don't know if that's exactly what you've implemented but I assume it's similar. So the explanation was for anyone trying to achieve a similar effect than the one you explained.

I've modified the example to also implement what I tried to explain in the last post. So now the example includes two ColorLines, an horizontal and a vertical. The horizontal line does the same than before: the points/line segments below the colorline are drawn in red.
The vertical line does what I understand you are trying to achieve: the points/line segments on the left of the colorline are drawn using a circle pointer and dashed line.
testInterpolation.zip
(3.69 KiB) Downloaded 601 times
It seems to work fine for me here, and I can move the mouse around the chart without missing any of the features:
interpolate.png
interpolate.png (37.84 KiB) Viewed 16202 times
If you find your solution should be correct but it still doesn't work as expected, I'd ask you to arrange a simple example project we can run as-is to reproduce the problem here, as mentioned at the end of my last post.
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

ix07
Newbie
Newbie
Posts: 11
Joined: Wed Apr 15, 2015 12:00 am

Re: Dynamic LinePen

Post by ix07 » Thu May 28, 2015 1:16 pm

Hi.

I made an example project where you can (hopefully) see the problem.

If you start the resulting application and make sure that the mouse cursor is not above the diagram when starting the application you will see a correctly drawn diagram. If you move the mouse cursor over the diagram window the first segment line style reverts to psSolid.

Thank you for help so far.
Attachments
LineStyle.zip
(88.83 KiB) Downloaded 594 times

ix07
Newbie
Newbie
Posts: 11
Joined: Wed Apr 15, 2015 12:00 am

Re: Dynamic LinePen

Post by ix07 » Thu May 28, 2015 1:59 pm

I simplified the example project and removed all unnecessary code.
Attachments
LineStyle.zip
(125.94 KiB) Downloaded 597 times

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

Re: Dynamic LinePen

Post by Yeray » Fri May 29, 2015 9:40 am

Hello,

Note OnBeforeDrawSeries is called once and it's called by the TChart. It's not called from the Series.
So TObject* sender is the chart, not the Series.
This works for me:

Code: Select all

void __fastcall TForm1::OnBeforeDrawSeries(TObject* sender)
{
  if(TChart* const chart = dynamic_cast<TChart*>(sender)) {

	for (int i = 0; i < chart->SeriesCount(); i++) {
	  if(TLineSeries* const lineSeries = dynamic_cast<TLineSeries*>(chart->Series[i]))
		lineSeries->LinePen->Style = psDot;
	}
  }
   /*if(TLineSeries* const lineSeries = dynamic_cast<TLineSeries*>(sender))
	  lineSeries->LinePen->Style = psDot;*/
}
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

ix07
Newbie
Newbie
Posts: 11
Joined: Wed Apr 15, 2015 12:00 am

Re: Dynamic LinePen

Post by ix07 » Fri May 29, 2015 10:27 am

You are absolutely right - i didn't see that.

Thank you very much for your help. Much appreciated!

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

Re: Dynamic LinePen

Post by Yeray » Fri May 29, 2015 10:38 am

Hi,
ix07 wrote:You are absolutely right - i didn't see that.

Thank you very much for your help. Much appreciated!
You are welcome! I'm glad to hear it finally works as you wish.
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