Steema Issues Database

Note: This database is for bugs and wishes only. For technical support help, if you are a customer please visit our online forums;
otherwise you can use StackOverflow.
Before using this bug-tracker we recommend a look at this document, Steema Bug Fixing Policy.



Bug 653

Summary: Update to Bug 651 : Problems with FastLine.MinMax
Product: .NET TeeChart Reporter: loeffler
Component: ChartAssignee: Steema Issue Manager <issuemanager>
Status: RESOLVED FIXED    
Severity: enhancement CC: chris
Priority: ---    
Version: TeeChart.NET 2014 4.1.2014.02060   
Target Milestone: ---   
Hardware: PC   
OS: Windows   
Chart Series: --- Delphi / C++ Builder RAD IDE Version:
Attachments: Three plots in zip file to illustrate the problem.
Screenshot of compressed chart with modified code

Description loeffler 2014-03-20 05:35:29 EDT
Created attachment 127 [details]
Three plots in zip file to illustrate the problem.

Dear Support

Thanks for your fast replay. Of course I read the reasons for closing the bug. But in my opinion the behavior of the FastLine MinMax is incorrect. Please try the following code:

            tChart1.Aspect.View3D = false;
            tChart1.Dock = DockStyle.Fill;
            fastLine1.AutoRepaint = false;
            fastLine1.LinePen.UseStyling = false;
            fastLine1.XValues.Order = ValueListOrder.None;
            fastLine1.DrawAllPoints = false;
            for (int i = 0; i < 10000; i++)
            {
                fastLine1.Add(i, Math.Sin(2*Math.PI * i/100));
            }
            fastLine1.DrawAllPointsStyle = DrawAllPointsStyle.MinMax;
            fastLine1.VertAxis = VerticalAxis.Left;
            fastLine1.HorizAxis = HorizontalAxis.Bottom;
  
It creates a sinus of 100 periods, with a maximum and minimum of 1. If the chart is wide enough you can see each period with min/max of 1. When you resize the plot horizontally you will see that the maximum remains at 1 (correct), but the minimum varies depending on the horizontal size of the plot (incorrect). Especially, when the horizontal plot size is rather small the effect is dramatic. My understanding of an min/max function is, that the plot shows the minimum and maximum value of the trace data which represent a single pixel.
For example, if a single pixel represents one or more periods of a sinus with amplitude +-1, the plot should show a line from -1 to +1. This is not the case in version 2014. 

I have attached three pictures illustrating the effect when resizing the plot horizontally.

I hope I was able to explain the problem we have. As I mentioned before the correct min/max feature is critical for us. Otherwise we have to switch to another component (what we do not want, because we like to work with TeeCharts).

It would be nice if you can fix the problem.
Thank you very much.
Hans Löffler
Comment 1 christopher ireland 2014-03-20 10:20:33 EDT
*** Bug 651 has been marked as a duplicate of this bug. ***
Comment 2 christopher ireland 2014-03-20 10:57:09 EDT
"My understanding of an min/max function is, that the plot shows the minimum and maximum value of the trace data which represent a single pixel."

That is also my understanding.

"For example, if a single pixel represents one or more periods of a sinus with amplitude +-1, the plot should show a line from -1 to +1. This is not the case in version 2014."

This is what the code looks like (simplified slightly, but with identical results):

        CalcPosition(index, ref X, ref Y);

        if (true/*ShouldDrawPoint(index, ref X, ref Y)*/)
        {
          if (!drawAll && drawAllStyle == Styles.DrawAllPointsStyle.MinMax)
          {
            if (X == oldX)
            {
              if (Y < iMin) iMin = Y;
              if (Y > iMax) iMax = Y;
              sameX = true;

              if (index == lastVisible)
              {
                DoDrawPoint(index, oldX, GetVertAxis.Inverted ? iMax : iMin);
              }
            }
            else
            {
              if (sameX)
              {
                DoDrawPoint(index, oldX, GetVertAxis.Inverted ? iMax : iMin);
              }

              DoDrawPoint(index, X, Y);

              sameX = false;
              iMin = int.MaxValue;
              iMax = int.MinValue;
            }
          } 

So first we calculate the pixel positions of the X and Y values. Then, if the X pixel position is the same as the X pixel position of the last point drawn, we cache the highest and lowest Y pixel positions. Then when the next X pixel position is different, we draw cached X and Y pixel positions and the next X and Y pixel positions.

Please bear in mind that the maximum and minimum Y pixel positions are only cached when the X pixel positions are identical. This does not necessarily mean that the cached Y pixel positions are going to represent the full amplitude of the Y value positions (+-1 in this case).

What I'm exposing here is how the code presently works, and how it fits in to what we both understand as a min/max function. 

I am not at all averse to creating a new DrawAllPointsStyle enum value that fits in with what you need, but in my opinion the min/max function presently works correctly according to what I understand as its design paradigm. Maybe you could help me design this new DrawAllPointsStyle, suggesting a name and which iMax and iMin values you would like to see cached when the X pixel values are identical.

Thank you.
Comment 3 loeffler 2014-04-01 04:07:55 EDT
I respond to the last EMail from Chris

Did you have a look at my three pictures of my last report? How do you interpret the shapes of the data, espcially
the asymetry beween upper and lower limit on the last picture, where the data are most horizontally compressed?
Did you try out my code, so that you can see the effect for yourself?

I'll try again to explain why this is really a MAJOR bug:
Take e.g. a sine wave with amplitude +-1. When you narrow down the display, so that the a single periond falls into 1 pixel, the display MUST SHOW a line from -1 to +1, The current version only goes to +1 but not to -1, see also comment at the end

> 
> Comment # 2 on bug 653 from christopher ireland 
> "My understanding of an min/max function is, that the plot shows the minimum
> and maximum value of the trace data which represent a single pixel."
> 
> That is also my understanding.
> 
> "For example, if a single pixel represents one or more periods of a sinus with
> amplitude +-1, the plot should show a line from -1 to +1. This is not the case
> in version 2014."
> 
 
> So first we calculate the pixel positions of the X and Y values. 
> Then, if the X
> pixel position is the same as the X pixel position of the last pointdrawn, we
> cache the highest and lowest Y pixel positions. Then when the next X pixel
> position is different, we draw cached X and Y pixel positions and the next X
> and Y pixel positions.

That seems plausible, however if the min and max fall on the same pixel (as is the case
when e.g a sine wave with many periods is compressed to very few pixels), the full amplitude
-1 and + 1 should be drawn for this pixel.

> 
> Please bear in mind that the maximum and minimum Y pixel positions are only
> cached when the X pixel positions are identical. This does not 
> necessarily mean
> that the cached Y pixel positions are going to represent the full amplitude of
> the Y value positions (+-1 in this case).

I do think so! If on one pixel the whole range between -1 and + 1 is represented,
there should be a (in this case vertical) line from -1 to +1 in the plot.
You apparently only do this for the max value as shown on my picture where data is completely
comprssed: there the upper limmit is OK, but on each pixel the min value is -1, so the
lines should go down there too!

best regards
Hans
Comment 4 christopher ireland 2014-04-01 07:26:19 EDT
Hans,

If I change this code:


              if (index == lastVisible)
              {
                DoDrawPoint(index, oldX, GetVertAxis.Inverted ? iMax : iMin);
              }
            }
            else
            {
              if (sameX)
              {
                DoDrawPoint(index, oldX, GetVertAxis.Inverted ? iMax : iMin);
              }

to this:

              if (index == lastVisible)
              {
                DoDrawPoint(index, oldX, GetVertAxis.Inverted ? iMax : iMin);
                DoDrawPoint(index, oldX, GetVertAxis.Inverted ? iMin : iMax);
              }
            }
            else
            {
              if (sameX)
              {
                DoDrawPoint(index, oldX, GetVertAxis.Inverted ? iMax : iMin);
                DoDrawPoint(index, oldX, GetVertAxis.Inverted ? iMin : iMax);
              }

then I get the plot in the attachment (modified.PNG). I think this could be fix you are looking for - instead of plotting only the (oldX, iMax) value, we are also plotting the (oldX, iMin) value.
Comment 5 christopher ireland 2014-04-01 07:27:18 EDT
Created attachment 146 [details]
Screenshot of compressed chart with modified code
Comment 6 loeffler 2014-04-01 10:10:32 EDT
The screenshot from comment #5 is exactly how we think that the plot should look like!
Do you consider to issue this fix soon?

Thank you
Hans
Comment 7 christopher ireland 2014-04-02 09:03:29 EDT
Hans,

The next maintenance release will contain this fix and will become publicly available before the end of this month. 

In the meantime, there is a possibility of deriving your own class from FastLine and overriding the DrawValue() method - this will mean re-implementing some private methods, code for which you could copy by opening TeeChart.dll in Reflector (or equivalent). The fix is nothing other than adding in the two lines I indicated.

Thank you.