[SOLVED] is it possible to have a constant bar type plot? lazarus / 55-TAChart ---------------------------------------------------------------------- madepabloh · 2012-10-12 17:35 Let me explain what i want to do: I have a temperature vs date-time plot . I used the calendar dialog to obtain the dates to plot two vertical constant lines corresponding to the starting and finish points of the period in which the temperature remains below 0ºC. For the moment i am working on the visual part, so instead to have two lines at the beganing and end of this period, i think it could be more visual to have a bar-like plot. However, it have two problems for what i want: 1) It is not constant on vertical such as it is the constant line plot. 2) It is opake, and covers the grid lines of the plot. So, my question are: is it possible to have something like a constant line but with the width defined by two x points? and is it possible to have the bar below the grid of the plot? Thanks! ---------------------------------------------------------------------- wp · 2012-10-12 19:49 Sorry, I don't quite understand. Maybe you should post a sketch of what you want to achieve. ---------------------------------------------------------------------- madepabloh · 2012-10-12 20:14 Excuse me, my english is not good enough: I attach an image showing what i have now and what i would like to have: a bar-type plot, with infinite limits in Y-axis, and width (x-axis) defined by two values i provide, with similar behaviour than Constant line type of plot. It is more clear in the image (i think). Thanks! ---------------------------------------------------------------------- wp · 2012-10-12 22:57 Maybe there are better solutions, but if you have special drawing requirements you can use the OnAfterDraw* events provided by chart. In this case, I think the correct one is OnAfterDrawBackWall. You may use the following event handler: Code: [Select]uses   LCLIntf;  // for rgb function procedure TForm1.Chart1AfterDrawBackWall(ASender: TChart; ACanvas: TCanvas;   const ARect: TRect); var   R: TRect;   p1, p2: integer; begin   p1 := Chart1.XGraphToImage(Chart1ConstantLine1.Position);   p2 := Chart1.XGraphToImage(Chart1ConstantLine2.Position);   R := Rect(p1, ARect.Top+1, p2, ARect.Bottom);   ACanvas.Brush.Style := bsSolid;   ACanvas.Brush.Color := rgb(220, 230, 210);   ACanvas.FillRect(R); end;  This procedure converts the positions of the two vertical lines to pixel coordinates. Then it paints a rectangle over the background before axes, grid, series etc. are drawn. Therefore, the rectangle does not cover any details of your chart. ---------------------------------------------------------------------- madepabloh · 2012-10-13 06:47 Thanks @WP (one more time), It works nice. I don´t know if, such as you said, it is the better solution or not, but it worls perfect!! So, i will work around this solution to adapt it to my proyect. Thanks so much! ---------------------------------------------------------------------- madepabloh · 2012-10-13 07:31 I have now a small problem with this solution: when i do zoom or paning, the painted area goes outside the limits of the plot, crossing and covering the axis (but not the markers and tittle... Take a look to the image i post here. It only occurs in the vertical axis, but not in the horizontal ones. However, i will also would like to apply this solution to horizontal constant lines, so probably the problem will be similar but for the x-axis. ---------------------------------------------------------------------- wp · 2012-10-13 09:36 When you zoom or pan the vertical lines may move out of the chart area. But in my code the background rectangle is always drawn between the vertical lines, so it will paint over the left axis if the left marker is beyond the left axis -- there is no automatic clipping. What you may do is to check the left edge of the x axis as a limit, this is Chart1.CurrentExtent.a.x. Therefore: Code: [Select]uses   TAChartUtils, math; var   ex: TDoubleRect; // ...   ex := Chart1.CurrentExtent;   p1 := Chart1.XGraphToImage(Max(Chart1ConstantLine1.Position, ex.a.x));   p2 := Chart1.XGraphToImage(Min(Chart1ConstantLine2.Position, ex.b.x)); This also takes care of the right edge of the chart. Not tested, but should work as long as you don't use transformations... ---------------------------------------------------------------------- wp · 2012-10-13 10:43 It's even simpler than that because the coordinates of the "back wall" as passed to the event handler, the extent calculatation therefore is not needed. Code: [Select]uses   Math; // ...   p1 := Chart1.XGraphToImage(Max(Chart1ConstantLine1.Position, ARect.Left));   p2 := Chart1.XGraphToImage(Max(Chart1ConstantLine1.Position, ARect.Right)); Maybe you'll have to add 1 to ARect.Left if the left edge of the frame is painted over. ---------------------------------------------------------------------- madepabloh · 2012-10-13 10:59 Hi WP, I was writing to you when you included this new option. So, i observed that the previous solution worked better. Efectively, I made +1 to the left side and -1 to the right in order to remain the axis visible. However there was other small problem. It works perfect except in the case both sides of the rectangle will be outside the plot area. In that cases, the rentangle is draw outside the plot area and the vertical axis also dissapear. You can see an image of this problem below. However, with your new possible solution, it does not work at all, and produce the same results: the rentangle goes outside the plot area when one of the limits is outside... So, looks like the first solution is better, except for the small issue i explain above. EDITED In the figure, i panned the plot area to the right, so the rectagle should dessapear by the left side, but is was still drawn outside the left edge of the plot. The same occurs in the right side. Meanwhile one of the limits is inside the plot area, the first solution works perfect. ---------------------------------------------------------------------- wp · 2012-10-13 13:40 QuoteHowever, with your new possible solution, it does not work at allThe curse of "copy & paste": for p2 the "Max" should be changed to "Min"... Quoteworks perfect except in the case both sides of the rectangle will be outside the plot areaThe curse of "quick & dirty": my code did not handle all cases correctly. Exit the procedure, when the right bar is at a position left of the left edge, and for the left bar accordingly. Maybe this should be better: Code: [Select]uses   LCLIntf;  // for rgb function procedure TForm1.Chart1AfterDrawBackWall(ASender: TChart; ACanvas: TCanvas;   const ARect: TRect); var   R: TRect;   p1, p2: integer; begin   p1 := Chart1.XGraphToImage(Chart1ConstantLine1.Position);  // left bar   if p1 >= ARect.Right then exit;   p2 := Chart1.XGraphToImage(Chart1ConstantLine2.Position);  // right bar   if p2 <= ARect.Left then exit;   R := Rect(Max(p1, ARect.Left+1), ARect.Top+1, Min(p2, ARect.Right-1), ARect.Bottom-1);   ACanvas.Brush.Style := bsSolid;   ACanvas.Brush.Color := rgb(220, 230, 210);   ACanvas.FillRect(R); end; ---------------------------------------------------------------------- Ask · 2012-10-13 15:08 Note that you can also solve the problem in the manner originally suggested by madepabloh: Add area series with two points having very large Y value, limit chart extent using Extent property. This solution also suffers from the problem of overriding chart frame. This problem (which also exhibited itself when zooming and panning various series) should be radically fixed by r39067. Since r39070, you can also use Infinity instead of arbitrary large Y value in area series, obviating the need to set chart extent manually. ---------------------------------------------------------------------- madepabloh · 2012-10-13 16:30 @wp, Yes, i made different changes trying to solve with my very low knowledge. I captured this issue. In the same way, in the last code it is also necessary Math declaration in uses. Thanks so much @wp. Now it works perfect. I tested in different ways, and works correctly, independently of zooming, panning, resizing of the chart, change of the constant line series,.... So definitively [Solved] what i required. It was not the idea i had on mind, but i am a dummie, so the solution is perfect for me. @Ask, Thanks to think about too. Yes, other was the solution i primary thought about, but just think it was possible to do, because i don´t know in detail all the possibilities and corners of chart. Thanks for improve the tool! So, definitively solved my wish! Thanks folks!