tags:

views:

406

answers:

1

I'm hoping someone may have the answer to this one

I've added some "PointPair" values to a ZedGraph graph, and this all works fine. However, when I show Symbols, it only shows the symbol on the high value, not the low value.

Does anyone know what could be causing this?

EDIT - Code Sample (sorry, I should've put this on yesterday)

// GraphPane pane (field)

FilledLineItem filledLineItem = new FilledLineItem("myline", upperPoints, lowerPoints, Color.DodgerBlue, ZedGraph.SymbolType.Square)
pane.CurveList.Add(filledLineItem);

Where upperPoints and lowerPoints are of type PointPairList

A: 

I have discovered the problem in the ZedGraph library...someone please correct me if I've missed something I shouldn't have

When using a FilledLineItem, this has a set of upper points and lower points.

When "Draw" is called, it is called on the LineItem class - which only has a set of points.

So I have added to the Draw method:

DrawPoints(pane, maxX, maxY, curve, curve.LowerPoints, g, source, scaleFactor, minX, minY, isPixelDrawn)

DrawPoints is a method that I extracted out of the "Draw" method in "Symbol". It contains the following

    private void DrawPoints(GraphPane pane, int maxX, int maxY, LineItem curve, IPointList points, Graphics g, Symbol source, float scaleFactor, int minX, int minY, bool[,] isPixelDrawn)
    {
        double curX;
        double curY;
        int tmpX;
        int tmpY;
        double lowVal;
        if ( points != null && ( _border.IsVisible || _fill.IsVisible ) )
        {
            SmoothingMode sModeSave = g.SmoothingMode;
            if ( _isAntiAlias )
                g.SmoothingMode = SmoothingMode.HighQuality;

            // For the sake of speed, go ahead and create a solid brush and a pen
            // If it's a gradient fill, it will be created on the fly for each symbol
            //SolidBrush brush = new SolidBrush( this.fill.Color );

            using ( Pen pen = source._border.GetPen( pane, scaleFactor ) )
            using ( GraphicsPath path = MakePath( g, scaleFactor ) )
            {
                RectangleF rect = path.GetBounds();

                using ( Brush brush = source.Fill.MakeBrush( rect ) )
                {
                    ValueHandler valueHandler = new ValueHandler( pane, false );
                    Scale xScale = curve.GetXAxis( pane ).Scale;
                    Scale yScale = curve.GetYAxis( pane ).Scale;

                    bool xIsLog = xScale.IsLog;
                    bool yIsLog = yScale.IsLog;
                    bool xIsOrdinal = xScale.IsAnyOrdinal;

                    double xMin = xScale.Min;
                    double xMax = xScale.Max;

                    // Loop over each defined point       
                    for ( int i = 0; i < points.Count; i++ )
                    {
                        // Check that this symbol should be shown, if not, then continue to the next symbol
                        if(!points[i].ShowSymbol)
                        {
                            continue;
                        }

                        // Get the user scale values for the current point
                        // use the valueHandler only for stacked types
                        if ( pane.LineType == LineType.Stack )
                        {
                            valueHandler.GetValues( curve, i, out curX, out lowVal, out curY );
                        }
                            // otherwise, just access the values directly.  Avoiding the valueHandler for
                            // non-stacked types is an optimization to minimize overhead in case there are
                            // a large number of points.
                        else
                        {
                            curX = points[i].X;
                            if ( curve is StickItem )
                                curY = points[i].Z;
                            else
                                curY = points[i].Y;
                        }

                        // Any value set to double max is invalid and should be skipped
                        // This is used for calculated values that are out of range, divide
                        //   by zero, etc.
                        // Also, any value <= zero on a log scale is invalid

                        if ( curX != PointPair.Missing &&
                             curY != PointPair.Missing &&
                             !System.Double.IsNaN( curX ) &&
                             !System.Double.IsNaN( curY ) &&
                             !System.Double.IsInfinity( curX ) &&
                             !System.Double.IsInfinity( curY ) &&
                             ( curX > 0 || !xIsLog ) &&
                             ( !yIsLog || curY > 0.0 ) &&
                             ( xIsOrdinal || ( curX >= xMin && curX <= xMax ) ) )
                        {
                            // Transform the user scale values to pixel locations
                            tmpX = (int) xScale.Transform( curve.IsOverrideOrdinal, i, curX );
                            tmpY = (int) yScale.Transform( curve.IsOverrideOrdinal, i, curY );

                            // Maintain an array of "used" pixel locations to avoid duplicate drawing operations
                            if ( tmpX >= minX && tmpX <= maxX && tmpY >= minY && tmpY <= maxY ) // guard against the zoom-in case
                            {
                                if ( isPixelDrawn[tmpX, tmpY] )
                                    continue;
                                isPixelDrawn[tmpX, tmpY] = true;
                            }

                            // If the fill type for this symbol is a Gradient by value type,
                            // the make a brush corresponding to the appropriate current value
                            if ( _fill.IsGradientValueType || _border._gradientFill.IsGradientValueType )
                            {
                                using ( Brush tBrush = _fill.MakeBrush( rect, points[i] ) )
                                using ( Pen tPen = _border.GetPen( pane, scaleFactor, points[i] ) )
                                    this.DrawSymbol( g, tmpX, tmpY, path, tPen, tBrush );
                            }
                            else
                            {
                                // Otherwise, the brush is already defined
                                // Draw the symbol at the specified pixel location
                                this.DrawSymbol( g, tmpX, tmpY, path, pen, brush );
                            }
                        }
                    }
                }
            }

            g.SmoothingMode = sModeSave;
        }
    }

So my "Draw" method now looks like this:

    public void Draw( Graphics g, GraphPane pane, LineItem curve, float scaleFactor,
  bool isSelected )
 {
  Symbol source = this;
  if ( isSelected )
   source = Selection.Symbol;

  int tmpX, tmpY;

  int minX = (int)pane.Chart.Rect.Left;
  int maxX = (int)pane.Chart.Rect.Right;
  int minY = (int)pane.Chart.Rect.Top;
  int maxY = (int)pane.Chart.Rect.Bottom;

  // (Dale-a-b) we'll set an element to true when it has been drawn 
  bool[,] isPixelDrawn = new bool[maxX + 1, maxY + 1];

        double curX, curY, lowVal;
        DrawPoints(pane, maxX, maxY, curve, curve.Points, g, source, scaleFactor, minX, minY, isPixelDrawn);

        // Need to check if this is a "Filled" line item, if it is, it may have lower points, in which case the lower points need to be output as well
     FilledLineItem filledLineItem = curve as FilledLineItem;
        if (filledLineItem != null)
        {
            DrawPoints(pane, maxX, maxY, curve, filledLineItem.LowerPoints, g, source, scaleFactor, minX, minY, isPixelDrawn);
        }
 }

...after casting the curve to a FilledLineItem (but not before checking that it is actually a FilledLineItem).

This has fixed the problem, and I hope it helps anyone else who may have the same problem.

Paul
Can you go into a little more detail about what you actually did, because I am not following you. I added your line to the draw method and I got a ton of errors, did you do something else that wasn't in your answer? There is no DrawPoints method in the solution, so I am not sure where that even came from. Thanks.
bobert5064
Woops, it looks like I extracted out DrawPoints as a method so I could call it twice. I'll post the actual code in the answer
Paul