PDFsharp & MigraDoc Foundation
http://forum.pdfsharp.com/

DisplayBlanksAs not implemented
http://forum.pdfsharp.com/viewtopic.php?f=2&t=372
Page 1 of 1

Author:  ldelabre [ Sun Apr 13, 2008 12:32 pm ]
Post subject:  DisplayBlanksAs not implemented

Hello!

I'm using charts with series containing possible "blank" values. At first, I was happy to discover a DisplayBlanksAs property...
Then I realize that this property is not yet implemented....(quick search throught the source code) ;-(

Is anyone working on this already ?

Thanks
Ludovic.

Author:  ldelabre [ Thu Apr 17, 2008 5:44 pm ]
Post subject: 

Since I received no answers, I assumed noboby's working on it..

So here's a first try - I know it's kindda ugly... (sorry ! :oups:) And I've not tested all modes yet ... Just wanted to shared this ;)

Code:
   /// <summary>
    /// Draws the content of the line plot area.
    /// </summary>
    internal override void Draw()
    {
      ChartRendererInfo cri = (ChartRendererInfo)this.rendererParms.RendererInfo;

      XRect plotAreaRect = cri.plotAreaRendererInfo.Rect;
      if (plotAreaRect.IsEmpty)
        return;

      XGraphics gfx = this.rendererParms.Graphics;
      XGraphicsState state = gfx.Save();
      gfx.SetClip(plotAreaRect, XCombineMode.Intersect);

      //TODO null-Values müssen berücksichtigt werden.
      //     Verbindungspunkte können fehlen, je nachdem wie null-Values behandelt werden sollen.
      //     (NotPlotted, Interpolate etc.)

      // Draw lines and markers for each data series.
      XMatrix matrix = cri.plotAreaRendererInfo.matrix;

      double xMajorTick = cri.xAxisRendererInfo.MajorTick;
      foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
      {
        int count = sri.series.Elements.Count;
        double[] values = new double[count];

        double left = double.NaN;
        int leftIdx = 0;
        for (int idx = 0; idx < count; idx++)
        {
            double v = sri.series.Elements[idx].Value;
            if (double.IsNaN(v))
            {
                switch (cri.chart.displayBlanksAs)
                {
                    case BlankType.NotPlotted:
                        v = double.NaN;
                        break;
                    case BlankType.Interpolated:
                        double right;
                        int rightIdx;

                        right = double.NaN; rightIdx = 0;
                        for (int jdx = idx + 1; jdx < count; jdx++)
                        {
                            double w = sri.series.Elements[jdx].Value;
                            if (!double.IsNaN(w))
                            {
                                right = w;
                                rightIdx = jdx;
                                break;
                            }
                        }
                        if (double.IsNaN(rightIdx) || double.IsNaN(leftIdx))
                            v = double.NaN;
                        else
                            v = (right - left) / (rightIdx - leftIdx);                       
                        break;
                    case BlankType.Zero:
                        v = 0;
                        break;
                    default:
                        throw new NotImplementedException();
                }
            }
            else
                left = v;
            values[idx] = v;           
        }

        List<List<XPoint>> points;
        points = new List<List<XPoint>>();
        points.Add(new List<XPoint>());
        for (int idx = 0; idx < count; idx++)
        {
          double v = sri.series.Elements[idx].Value;
          if (double.IsNaN(v))
          {
              if (points[points.Count -1].Count > 0)
                points.Add(new List<XPoint>());
          }
          else
              points[points.Count - 1].Add(new XPoint(idx + xMajorTick / 2, v));
        }
        foreach (List<XPoint> lines in points)
        {
            if (lines.Count > 0)
            {
                XPoint[] pts;

                pts = lines.ToArray();
                matrix.TransformPoints(pts);
                if (pts.Length > 2)
                    gfx.DrawLines(sri.LineFormat, pts);
                DrawMarker(gfx, pts, sri);
            }
        }
      }

      gfx.ResetClip();
      gfx.Restore(state);
    }

Author:  ldelabre [ Sun Jun 15, 2008 1:59 pm ]
Post subject: 

Oups... bug :oops:

I do correct myself :D

Code:
              if (pts.Length > 2)


should be

Code:
              if (pts.Length >= 2)

Author:  steve.nottage [ Wed Oct 13, 2010 1:02 pm ]
Post subject:  Re: DisplayBlanksAs not implemented

Hi,

I have charts with series that have missing data points. I would like to be able to use the functionality DisplayBlanksAs. The original post was over 2 years ago, however this still appears to be non-functional as when I try to use it the missing data point is set to zero (null) instead of being processed and skipped.

I have been looking to implement the code suggested by ldelabre, however I am unsure where it should go.

Can anyone help me

Many thanks
Steve

Author:  Thomas Hoevel [ Wed Oct 13, 2010 3:07 pm ]
Post subject:  Re: DisplayBlanksAs not implemented

Hi, Steve!
steve.nottage wrote:
I have been looking to implement the code suggested by ldelabre, however I am unsure where it should go.

Just enter "Draws the content of the line plot area." into Visual Studio's Search Dialogue and it'll take you to
"PDFsharp\code\PdfSharp.Charting\PdfSharp.Charting.Renderers\LinePlotAreaRenderer.cs(50)"

Author:  SteffenB [ Thu Mar 31, 2011 9:40 am ]
Post subject:  Re: DisplayBlanksAs not implemented

OK, this little hack seems to work fine!
But I don't understand this line:
Code:
points[points.Count - 1].Add(new XPoint(idx + xMajorTick / 2, v));

imho this will "move" the whole line a half xMajorTickmark to the right. Why do you do this?
After using
Code:
points[points.Count - 1].Add(new XPoint(idx, v));

it looks better to me

Regards Steffen

Author:  thebarnastyle [ Wed Sep 21, 2022 8:58 am ]
Post subject:  Re: DisplayBlanksAs not implemented

Hi guys,

Thank you so much for the solution. It saved my life. I don't know how this was not implemented because it's a must on a lot of line charts types.
I used that solution but was not working on the version of PdfSharp that I've downloaded from that link https://sourceforge.net/projects/pdfsharp/ provided on that official website http://www.pdfsharp.net/Downloads.ashx

On that version, there're some differences between the solution given of this post and I had to change it. I past here my code that is currently working on that version.

/**/
// <summary>
/// Draws the content of the line plot area.
/// </summary>
internal override void Draw()
{
ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;

XRect plotAreaRect = cri.plotAreaRendererInfo.Rect;
if (plotAreaRect.IsEmpty)
return;

XGraphics gfx = _rendererParms.Graphics;
XGraphicsState state = gfx.Save();
//gfx.SetClip(plotAreaRect, XCombineMode.Intersect);
gfx.IntersectClip(plotAreaRect);

//TODO Treat null values correctly.
// Points can be missing. Treat null values accordingly (NotPlotted, Interpolate etc.)

// Draw lines and markers for each data series.
XMatrix matrix = cri.plotAreaRendererInfo._matrix;

double xMajorTick = cri.xAxisRendererInfo.MajorTick;
foreach (SeriesRendererInfo sri in cri.seriesRendererInfos)
{
int count = sri._series.Elements.Count;
double[] values = new double[count];

double left = double.NaN;
int leftIdx = 0;
for (int idx = 0; idx < count; idx++)
{
double v = sri._series.Elements[idx].Value;
if (double.IsNaN(v))
{
switch (cri._chart._displayBlanksAs)
{
case BlankType.NotPlotted:
v = double.NaN;
break;
case BlankType.Interpolated:
double right;
int rightIdx;

right = double.NaN; rightIdx = 0;
for (int jdx = idx + 1; jdx < count; jdx++)
{
double w = sri._series.Elements[jdx].Value;
if (!double.IsNaN(w))
{
right = w;
rightIdx = jdx;
break;
}
}
if (double.IsNaN(rightIdx) || double.IsNaN(leftIdx))
v = double.NaN;
else
v = (right - left) / (rightIdx - leftIdx);
break;
case BlankType.Zero:
v = 0;
break;
default:
throw new NotImplementedException();
}
}
else
left = v;
values[idx] = v;
}

List<List<XPoint>> points;
points = new List<List<XPoint>>();
points.Add(new List<XPoint>());
for (int idx = 0; idx < count; idx++)
{
double v = sri._series.Elements[idx].Value;
if (double.IsNaN(v))
{
if (points[points.Count - 1].Count > 0)
points.Add(new List<XPoint>());
}
else
points[points.Count - 1].Add(new XPoint(idx + xMajorTick / 2, v));
}
foreach (List<XPoint> lines in points)
{
if (lines.Count > 0)
{
XPoint[] pts;

pts = lines.ToArray();
matrix.TransformPoints(pts);
if (pts.Length >= 2)
gfx.DrawLines(sri.LineFormat, pts);
DrawMarker(gfx, pts, sri);
}
}
}

//gfx.ResetClip();
gfx.Restore(state);
}
/**/

Also, big thanks to "ldelabre" to provide us a working version so I only had to change some part of the code to be able to work for me.

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/