PDFsharp & MigraDoc Foundation

PDFsharp - A .NET library for processing PDF & MigraDoc Foundation - Creating documents on the fly
It is currently Tue Mar 19, 2024 4:55 am

All times are UTC


Forum rules


Please read this before posting on this forum: Forum Rules



Post new topic Reply to topic  [ 7 posts ] 
Author Message
PostPosted: Sun Apr 13, 2008 12:32 pm 
Offline

Joined: Sat Apr 12, 2008 8:51 am
Posts: 10
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.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Apr 17, 2008 5:44 pm 
Offline

Joined: Sat Apr 12, 2008 8:51 am
Posts: 10
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);
    }


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Jun 15, 2008 1:59 pm 
Offline

Joined: Sat Apr 12, 2008 8:51 am
Posts: 10
Oups... bug :oops:

I do correct myself :D

Code:
              if (pts.Length > 2)


should be

Code:
              if (pts.Length >= 2)


Top
 Profile  
Reply with quote  
PostPosted: Wed Oct 13, 2010 1:02 pm 
Offline

Joined: Wed Oct 13, 2010 12:43 pm
Posts: 2
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


Top
 Profile  
Reply with quote  
PostPosted: Wed Oct 13, 2010 3:07 pm 
Offline
PDFsharp Guru
User avatar

Joined: Mon Oct 16, 2006 8:16 am
Posts: 3092
Location: Cologne, Germany
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)"

_________________
Regards
Thomas Hoevel
PDFsharp Team


Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 31, 2011 9:40 am 
Offline

Joined: Tue Mar 29, 2011 11:35 am
Posts: 2
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


Top
 Profile  
Reply with quote  
PostPosted: Wed Sep 21, 2022 8:58 am 
Offline

Joined: Wed Sep 21, 2022 8:17 am
Posts: 1
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.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 21 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Privacy Policy, Data Protection Declaration, Impressum
Powered by phpBB® Forum Software © phpBB Group