Example #1
0
        /// <summary>
        /// Draw the this <see cref="Bar"/> to the specified <see cref="Graphics"/>
        /// device as a bar at each defined point. This method
        /// is normally only called by the <see cref="BarItem.Draw"/> method of the
        /// <see cref="BarItem"/> object
        /// </summary>
        /// <param name="g">
        /// A graphic device object to be drawn into.  This is normally e.Graphics from the
        /// PaintEventArgs argument to the Paint() method.
        /// </param>
        /// <param name="pane">
        /// A reference to the <see cref="GraphPane"/> object that is the parent or
        /// owner of this object.
        /// </param>
        /// <param name="curve">A <see cref="CurveItem"/> object representing the
        /// <see cref="Bar"/>'s to be drawn.</param>
        /// <param name="baseAxis">The <see cref="Axis"/> class instance that defines the base (independent)
        /// axis for the <see cref="Bar"/></param>
        /// <param name="valueAxis">The <see cref="Axis"/> class instance that defines the value (dependent)
        /// axis for the <see cref="Bar"/></param>
        /// <param name="barWidth">
        /// The width of each bar, in pixels.
        /// </param>
        /// <param name="pos">
        /// The ordinal position of the this bar series (0=first bar, 1=second bar, etc.)
        /// in the cluster of bars.
        /// </param>
        /// <param name="scaleFactor">
        /// The scaling factor to be used for rendering objects.  This is calculated and
        /// passed down by the parent <see cref="GraphPane"/> object using the
        /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
        /// font sizes, etc. according to the actual size of the graph.
        /// </param>
        public void DrawBars(Graphics g, GraphPane pane, CurveItem curve,
                             Axis baseAxis, Axis valueAxis,
                             float barWidth, int pos, float scaleFactor)
        {
            // For non-cluster bar types, the position is always zero since the bars are on top
            // of eachother
            BarType barType = pane._barSettings.Type;

            if (barType == BarType.Overlay || barType == BarType.Stack || barType == BarType.PercentStack ||
                barType == BarType.SortedOverlay)
            {
                pos = 0;
            }

            // Loop over each defined point and draw the corresponding bar
            for (int i = 0; i < curve.Points.Count; i++)
            {
                DrawSingleBar(g, pane, curve, i, pos, baseAxis, valueAxis, barWidth, scaleFactor);
            }
        }
Example #2
0
        /// <summary>
        /// Draw the specified single bar (an individual "point") of this series to the specified
        /// <see cref="Graphics"/> device.  This method is not as efficient as
        /// <see cref="DrawBars"/>, which draws the bars for all points.  It is intended to be used
        /// only for <see cref="BarType.SortedOverlay"/>, which requires special handling of each bar.
        /// </summary>
        /// <param name="g">
        /// A graphic device object to be drawn into.  This is normally e.Graphics from the
        /// PaintEventArgs argument to the Paint() method.
        /// </param>
        /// <param name="pane">
        /// A reference to the <see cref="GraphPane"/> object that is the parent or
        /// owner of this object.
        /// </param>
        /// <param name="curve">A <see cref="CurveItem"/> object representing the
        /// <see cref="Bar"/>'s to be drawn.</param>
        /// <param name="baseAxis">The <see cref="Axis"/> class instance that defines the base (independent)
        /// axis for the <see cref="Bar"/></param>
        /// <param name="valueAxis">The <see cref="Axis"/> class instance that defines the value (dependent)
        /// axis for the <see cref="Bar"/></param>
        /// <param name="pos">
        /// The ordinal position of the this bar series (0=first bar, 1=second bar, etc.)
        /// in the cluster of bars.
        /// </param>
        /// <param name="index">
        /// The zero-based index number for the single bar to be drawn.
        /// </param>
        /// <param name="barWidth">
        /// The width of each bar, in pixels.
        /// </param>
        /// <param name="scaleFactor">
        /// The scaling factor to be used for rendering objects.  This is calculated and
        /// passed down by the parent <see cref="GraphPane"/> object using the
        /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
        /// font sizes, etc. according to the actual size of the graph.
        /// </param>
        public void DrawSingleBar(Graphics g, GraphPane pane, CurveItem curve,
                                  Axis baseAxis, Axis valueAxis,
                                  int pos, int index, float barWidth, float scaleFactor)
        {
            // Make sure that a bar value exists for the current curve and current ordinal position
            if (index >= curve.Points.Count)
            {
                return;
            }

            // For Overlay and Stack bars, the position is always zero since the bars are on top
            // of eachother
            if (pane._barSettings.Type == BarType.Overlay || pane._barSettings.Type == BarType.Stack ||
                pane._barSettings.Type == BarType.PercentStack)
            {
                pos = 0;
            }

            // Draw the specified bar
            DrawSingleBar(g, pane, curve, index, pos, baseAxis, valueAxis, barWidth, scaleFactor);
        }
Example #3
0
        /// <summary>
        /// The Copy Constructor
        /// </summary>
        /// <param name="rhs">The CurveItem object from which to copy</param>
        public CurveItem(CurveItem rhs)
            : base(rhs)
        {
            _label = rhs._label.Clone();
            //_isY2Axis = rhs.IsY2Axis;
            //_isX2Axis = rhs.IsX2Axis;
            _isVisible         = rhs.IsVisible;
            _isOverrideOrdinal = rhs._isOverrideOrdinal;
            _yAxisIndex        = rhs._yAxisIndex;

            if (rhs.Tag is ICloneable)
            {
                this.Tag = ((ICloneable)rhs.Tag).Clone();
            }
            else
            {
                this.Tag = rhs.Tag;
            }

            _points = (IPointList)rhs.Points.Clone();

            //_link = rhs._link.Clone();
        }
Example #4
0
        /// <summary>
        /// Calculate the <see cref="Legend"/> rectangle (<see cref="Rect"/>),
        /// taking into account the number of required legend
        /// entries, and the legend drawing preferences.
        /// </summary>
        /// <remarks>Adjust the size of the
        /// <see cref="Chart.Rect"/> for the parent <see cref="GraphPane"/> to accomodate the
        /// space required by the legend.
        /// </remarks>
        /// <param name="g">
        /// A graphic device object to be drawn into.  This is normally e.Graphics from the
        /// PaintEventArgs argument to the Paint() method.
        /// </param>
        /// <param name="pane">
        /// A reference to the <see cref="PaneBase"/> object that is the parent or
        /// owner of this object.
        /// </param>
        /// <param name="scaleFactor">
        /// The scaling factor to be used for rendering objects.  This is calculated and
        /// passed down by the parent <see cref="GraphPane"/> object using the
        /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
        /// font sizes, etc. according to the actual size of the graph.
        /// </param>
        /// <param name="tChartRect">
        /// The rectangle that contains the area bounded by the axes, in pixel units.
        /// <seealso cref="Chart.Rect" />
        /// </param>
        public void CalcRect(Graphics g, PaneBase pane, float scaleFactor,
                             ref RectangleF tChartRect)
        {
            // Start with an empty rectangle
            _rect             = Rectangle.Empty;
            _hStack           = 1;
            _legendItemWidth  = 1;
            _legendItemHeight = 0;

            RectangleF clientRect = pane.CalcClientRect(g, scaleFactor);

            // If the legend is invisible, don't do anything
            if (!_isVisible)
            {
                return;
            }

            int nCurve = 0;

            PaneList paneList = GetPaneList(pane);

            _tmpSize = GetMaxHeight(paneList, g, scaleFactor);

            float halfGap  = _tmpSize / 2.0F,
                  maxWidth = 0,
                  tmpWidth,
                  gapPix = _gap * _tmpSize;

            foreach (GraphPane tmpPane in paneList)
            {
                // Loop through each curve in the curve list
                // Find the maximum width of the legend labels
                //foreach ( CurveItem curve in tmpPane.CurveList )
                //foreach ( CurveItem curve in GetIterator( tmpPane.CurveList, _isReverse ) )
                int count = tmpPane.CurveList.Count;
                for (int i = 0; i < count; i++)
                {
                    CurveItem curve = tmpPane.CurveList[_isReverse ? count - i - 1 : i];
                    if (curve._label._text != string.Empty && curve._label._isVisible)
                    {
                        // Calculate the width of the label save the max width
                        FontSpec tmpFont = (curve._label._fontSpec != null) ?
                                           curve._label._fontSpec : this.FontSpec;

                        tmpWidth = tmpFont.GetWidth(g, curve._label._text, scaleFactor);

                        if (tmpWidth > maxWidth)
                        {
                            maxWidth = tmpWidth;
                        }

                        // Save the maximum symbol height for line-type curves
                        if (curve is LineItem && ((LineItem)curve).Symbol.Size > _legendItemHeight)
                        {
                            _legendItemHeight = ((LineItem)curve).Symbol.Size;
                        }

                        nCurve++;
                    }
                }

                if (pane is MasterPane && ((MasterPane)pane).IsUniformLegendEntries)
                {
                    break;
                }
            }

            float widthAvail;

            // Is this legend horizontally stacked?

            if (_isHStack)
            {
                // Determine the available space for horizontal stacking
                switch (_position)
                {
                // Never stack if the legend is to the right or left
                case LegendPos.Right:
                case LegendPos.Left:
                    widthAvail = 0;
                    break;

                // for the top & bottom, the axis border width is available
                case LegendPos.Top:
                case LegendPos.TopCenter:
                case LegendPos.Bottom:
                case LegendPos.BottomCenter:
                    widthAvail = tChartRect.Width;
                    break;

                // for the top & bottom flush left, the panerect less margins is available
                case LegendPos.TopFlushLeft:
                case LegendPos.BottomFlushLeft:
                    widthAvail = clientRect.Width;
                    break;

                // for inside the axis area or Float, use 1/2 of the axis border width
                case LegendPos.InsideTopRight:
                case LegendPos.InsideTopLeft:
                case LegendPos.InsideBotRight:
                case LegendPos.InsideBotLeft:
                case LegendPos.Float:
                    widthAvail = tChartRect.Width / 2;
                    break;

                // shouldn't ever happen
                default:
                    widthAvail = 0;
                    break;
                }

                // width of one legend entry
                if (_isShowLegendSymbols)
                {
                    _legendItemWidth = 3.0f * _tmpSize + maxWidth;
                }
                else
                {
                    _legendItemWidth = 0.5f * _tmpSize + maxWidth;
                }

                // Calculate the number of columns in the legend
                // Normally, the legend is:
                //     available width / ( max width of any entry + space for line&symbol )
                if (maxWidth > 0)
                {
                    _hStack = (int)((widthAvail - halfGap) / _legendItemWidth);
                }

                // You can never have more columns than legend entries
                if (_hStack > nCurve)
                {
                    _hStack = nCurve;
                }

                // a saftey check
                if (_hStack == 0)
                {
                    _hStack = 1;
                }
            }
            else
            {
                if (_isShowLegendSymbols)
                {
                    _legendItemWidth = 3.0F * _tmpSize + maxWidth;
                }
                else
                {
                    _legendItemWidth = 0.5F * _tmpSize + maxWidth;
                }
            }

            // legend is:
            //   item:     space  line  space  text   space
            //   width:     wid  4*wid   wid  maxWid   wid
            // The symbol is centered on the line
            //
            // legend begins 3 * wid to the right of the plot rect
            //
            // The height of the legend is the actual height of the lines of text
            //   (nCurve * hite) plus wid on top and wid on the bottom

            // total legend width
            float totLegWidth = _hStack * _legendItemWidth;

            // The total legend height
            _legendItemHeight = _legendItemHeight * (float)scaleFactor + halfGap;
            if (_tmpSize > _legendItemHeight)
            {
                _legendItemHeight = _tmpSize;
            }
            float totLegHeight = (float)Math.Ceiling((double)nCurve / (double)_hStack)
                                 * _legendItemHeight;

            RectangleF newRect = new RectangleF();

            // Now calculate the legend rect based on the above determined parameters
            // Also, adjust the ChartRect to reflect the space for the legend
            if (nCurve > 0)
            {
                newRect = new RectangleF(0, 0, totLegWidth, totLegHeight);

                // The switch statement assigns the left and top edges, and adjusts the ChartRect
                // as required.  The right and bottom edges are calculated at the bottom of the switch.
                switch (_position)
                {
                case LegendPos.Right:
                    newRect.X = clientRect.Right - totLegWidth;
                    newRect.Y = tChartRect.Top;

                    tChartRect.Width -= totLegWidth + gapPix;
                    break;

                case LegendPos.Top:
                    newRect.X = tChartRect.Left;
                    newRect.Y = clientRect.Top;

                    tChartRect.Y      += totLegHeight + gapPix;
                    tChartRect.Height -= totLegHeight + gapPix;
                    break;

                case LegendPos.TopFlushLeft:
                    newRect.X = clientRect.Left;
                    newRect.Y = clientRect.Top;

                    tChartRect.Y      += totLegHeight + gapPix * 1.5f;
                    tChartRect.Height -= totLegHeight + gapPix * 1.5f;
                    break;

                case LegendPos.TopCenter:
                    newRect.X = tChartRect.Left + (tChartRect.Width - totLegWidth) / 2;
                    newRect.Y = tChartRect.Top;

                    tChartRect.Y      += totLegHeight + gapPix;
                    tChartRect.Height -= totLegHeight + gapPix;
                    break;

                case LegendPos.Bottom:
                    newRect.X = tChartRect.Left;
                    newRect.Y = clientRect.Bottom - totLegHeight;

                    tChartRect.Height -= totLegHeight + gapPix;
                    break;

                case LegendPos.BottomFlushLeft:
                    newRect.X = clientRect.Left;
                    newRect.Y = clientRect.Bottom - totLegHeight;

                    tChartRect.Height -= totLegHeight + gapPix;
                    break;

                case LegendPos.BottomCenter:
                    newRect.X = tChartRect.Left + (tChartRect.Width - totLegWidth) / 2;
                    newRect.Y = clientRect.Bottom - totLegHeight;

                    tChartRect.Height -= totLegHeight + gapPix;
                    break;

                case LegendPos.Left:
                    newRect.X = clientRect.Left;
                    newRect.Y = tChartRect.Top;

                    tChartRect.X     += totLegWidth + halfGap;
                    tChartRect.Width -= totLegWidth + gapPix;
                    break;

                case LegendPos.InsideTopRight:
                    newRect.X = tChartRect.Right - totLegWidth;
                    newRect.Y = tChartRect.Top;
                    break;

                case LegendPos.InsideTopLeft:
                    newRect.X = tChartRect.Left;
                    newRect.Y = tChartRect.Top;
                    break;

                case LegendPos.InsideBotRight:
                    newRect.X = tChartRect.Right - totLegWidth;
                    newRect.Y = tChartRect.Bottom - totLegHeight;
                    break;

                case LegendPos.InsideBotLeft:
                    newRect.X = tChartRect.Left;
                    newRect.Y = tChartRect.Bottom - totLegHeight;
                    break;

                case LegendPos.Float:
                    newRect.Location = this.Location.TransformTopLeft(pane, totLegWidth, totLegHeight);
                    break;
                }
            }

            _rect = newRect;
        }
Example #5
0
        /// <summary>
        /// Render the <see cref="Legend"/> to the specified <see cref="Graphics"/> device.
        /// </summary>
        /// <remarks>
        /// This method is normally only called by the Draw method
        /// of the parent <see cref="GraphPane"/> object.
        /// </remarks>
        /// <param name="g">
        /// A graphic device object to be drawn into.  This is normally e.Graphics from the
        /// PaintEventArgs argument to the Paint() method.
        /// </param>
        /// <param name="pane">
        /// A reference to the <see cref="PaneBase"/> object that is the parent or
        /// owner of this object.
        /// </param>
        /// <param name="scaleFactor">
        /// The scaling factor to be used for rendering objects.  This is calculated and
        /// passed down by the parent <see cref="GraphPane"/> object using the
        /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust
        /// font sizes, etc. according to the actual size of the graph.
        /// </param>
        public void Draw(Graphics g, PaneBase pane, float scaleFactor)
        {
            // if the legend is not visible, do nothing
            if (!_isVisible)
            {
                return;
            }

            // Fill the background with the specified color if required
            _fill.Draw(g, _rect);

            PaneList paneList = GetPaneList(pane);

            float halfGap = _tmpSize / 2.0F;

            // Check for bad data values
            if (_hStack <= 0)
            {
                _hStack = 1;
            }
            if (_legendItemWidth <= 0)
            {
                _legendItemWidth = 100;
            }
            if (_legendItemHeight <= 0)
            {
                _legendItemHeight = _tmpSize;
            }

            //float gap = pane.ScaledGap( scaleFactor );

            int   iEntry = 0;
            float x, y;

            // Get a brush for the legend label text
            using (SolidBrush brushB = new SolidBrush(Color.Black))
            {
                foreach (GraphPane tmpPane in paneList)
                {
                    // Loop for each curve in the CurveList collection
                    //foreach ( CurveItem curve in tmpPane.CurveList )
                    int count = tmpPane.CurveList.Count;
                    for (int i = 0; i < count; i++)
                    {
                        CurveItem curve = tmpPane.CurveList[_isReverse ? count - i - 1 : i];

                        if (curve._label._text != "" && curve._label._isVisible)
                        {
                            // Calculate the x,y (TopLeft) location of the current
                            // curve legend label
                            // assuming:
                            //  charHeight/2 for the left margin, plus legendWidth for each
                            //    horizontal column
                            //  legendHeight is the line spacing, with no extra margin above

                            x = _rect.Left + halfGap / 2.0F +
                                (iEntry % _hStack) * _legendItemWidth;
                            y = _rect.Top + (int)(iEntry / _hStack) * _legendItemHeight;

                            // Draw the legend label for the current curve
                            FontSpec tmpFont = (curve._label._fontSpec != null) ?
                                               curve._label._fontSpec : this.FontSpec;

                            // This is required because, for long labels, the centering can affect the
                            // position in GDI+.
                            tmpFont.StringAlignment = StringAlignment.Near;

                            if (_isShowLegendSymbols)
                            {
                                tmpFont.Draw(g, pane, curve._label._text,
                                             x + 2.5F * _tmpSize, y + _legendItemHeight / 2.0F,
                                             AlignH.Left, AlignV.Center, scaleFactor);

                                RectangleF rect = new RectangleF(x, y + _legendItemHeight / 4.0F,
                                                                 2 * _tmpSize, _legendItemHeight / 2.0F);
                                curve.DrawLegendKey(g, tmpPane, rect, scaleFactor);
                            }
                            else
                            {
                                if (curve._label._fontSpec == null)
                                {
                                    tmpFont.FontColor = curve.Color;
                                }

                                tmpFont.Draw(g, pane, curve._label._text,
                                             x + 0.0F * _tmpSize, y + _legendItemHeight / 2.0F,
                                             AlignH.Left, AlignV.Center, scaleFactor);
                            }

                            // maintain a curve count for positioning
                            iEntry++;
                        }
                    }
                    if (pane is MasterPane && ((MasterPane)pane).IsUniformLegendEntries)
                    {
                        break;
                    }
                }

                // Draw a border around the legend if required
                if (iEntry > 0)
                {
                    this.Border.Draw(g, pane, scaleFactor, _rect);
                }
            }
        }
Example #6
0
        /// <summary>
        /// Get the user scale values associate with a particular point of a
        /// particular curve.</summary>
        /// <remarks>The main purpose of this method is to handle
        /// stacked bars and lines, in which case the stacked values are returned rather
        /// than the individual data values.  However, this method works generically for any
        /// curve type.
        /// </remarks>
        /// <param name="pane">The parent <see cref="GraphPane"/> object.</param>
        /// <param name="curve">A <see cref="CurveItem"/> object of interest.</param>
        /// <param name="iPt">The zero-based point index for the point of interest.</param>
        /// <param name="baseVal">A <see cref="Double"/> value representing the value
        /// for the independent axis.</param>
        /// <param name="lowVal">A <see cref="Double"/> value representing the lower
        /// value for the dependent axis.</param>
        /// <param name="hiVal">A <see cref="Double"/> value representing the upper
        /// value for the dependent axis.</param>
        /// <returns>true if the data point is value, false for
        /// <see cref="PointPairBase.Missing"/>, invalid, etc. data.</returns>
        public static bool GetValues(GraphPane pane, CurveItem curve, int iPt,
                                     out double baseVal, out double lowVal, out double hiVal)
        {
            hiVal   = PointPair.Missing;
            lowVal  = PointPair.Missing;
            baseVal = PointPair.Missing;

            if (curve == null || curve.Points.Count <= iPt || !curve.IsVisible)
            {
                return(false);
            }

            Axis baseAxis  = curve.BaseAxis(pane);
            Axis valueAxis = curve.ValueAxis(pane);

            if (baseAxis is XAxis || baseAxis is X2Axis)
            {
                baseVal = curve.Points[iPt].X;
            }
            else
            {
                baseVal = curve.Points[iPt].Y;
            }

            // is it a stacked bar type?
            if (curve is BarItem && (pane._barSettings.Type == BarType.Stack ||
                                     pane._barSettings.Type == BarType.PercentStack))
            {
                double positiveStack = 0;
                double negativeStack = 0;
                double curVal;

                // loop through all the curves, summing up the values to get a total (only
                // for the current ordinal position iPt)
                foreach (CurveItem tmpCurve in pane.CurveList)
                {
                    // Sum the value for the current curve only if it is a bar
                    if (tmpCurve.IsBar && tmpCurve.IsVisible)
                    {
                        curVal = PointPair.Missing;
                        // For non-ordinal curves, find a matching base value (must match exactly)
                        if (curve.IsOverrideOrdinal || !baseAxis._scale.IsAnyOrdinal)
                        {
                            IPointList points = tmpCurve.Points;

                            for (int i = 0; i < points.Count; i++)
                            {
                                if ((baseAxis is XAxis || baseAxis is X2Axis) && points[i].X == baseVal)
                                {
                                    curVal = points[i].Y;
                                    break;
                                }
                                else if (!(baseAxis is XAxis || baseAxis is X2Axis) && points[i].Y == baseVal)
                                {
                                    curVal = points[i].X;
                                    break;
                                }
                            }
                        }
                        // otherwise, it's an ordinal type so use the value at the same ordinal position
                        else if (iPt < tmpCurve.Points.Count)
                        {
                            // Get the value for the appropriate value axis
                            if (baseAxis is XAxis || baseAxis is X2Axis)
                            {
                                curVal = tmpCurve.Points[iPt].Y;
                            }
                            else
                            {
                                curVal = tmpCurve.Points[iPt].X;
                            }
                        }

                        // If it's a missing value, skip it
                        if (curVal == PointPair.Missing)
                        {
                            positiveStack = PointPair.Missing;
                            negativeStack = PointPair.Missing;
                        }

                        // the current curve is the target curve, save the summed values for later
                        if (tmpCurve == curve)
                        {
                            // if the value is positive, use the positive stack
                            if (curVal >= 0)
                            {
                                lowVal = positiveStack;
                                hiVal  = (curVal == PointPair.Missing || positiveStack == PointPair.Missing) ?
                                         PointPair.Missing : positiveStack + curVal;
                            }
                            // otherwise, use the negative stack
                            else
                            {
                                hiVal  = negativeStack;
                                lowVal = (curVal == PointPair.Missing || negativeStack == PointPair.Missing) ?
                                         PointPair.Missing : negativeStack + curVal;
                            }
                        }

                        // Add all positive values to the positive stack, and negative values to the
                        // negative stack
                        if (curVal >= 0)
                        {
                            positiveStack = (curVal == PointPair.Missing || positiveStack == PointPair.Missing) ?
                                            PointPair.Missing : positiveStack + curVal;
                        }
                        else
                        {
                            negativeStack = (curVal == PointPair.Missing || negativeStack == PointPair.Missing) ?
                                            PointPair.Missing : negativeStack + curVal;
                        }
                    }
                }

                // if the curve is a PercentStack type, then calculate the percent for this bar
                // based on the total height of the stack
                if (pane._barSettings.Type == BarType.PercentStack &&
                    hiVal != PointPair.Missing && lowVal != PointPair.Missing)
                {
                    // Use the total magnitude of the positive plus negative bar stacks to determine
                    // the percentage value
                    positiveStack += Math.Abs(negativeStack);

                    // just to avoid dividing by zero...
                    if (positiveStack != 0)
                    {
                        // calculate the percentage values
                        lowVal = lowVal / positiveStack * 100.0;
                        hiVal  = hiVal / positiveStack * 100.0;
                    }
                    else
                    {
                        lowVal = 0;
                        hiVal  = 0;
                    }
                }

                if (baseVal == PointPair.Missing || lowVal == PointPair.Missing ||
                    hiVal == PointPair.Missing)
                {
                    return(false);
                }
                else
                {
                    return(true);
                }
            }
            // If the curve is a stacked line type, then sum up the values similar to the stacked bar type
            else if (curve is LineItem && pane.LineType == LineType.Stack)
            {
                double stack = 0;
                double curVal;

                // loop through all the curves, summing up the values to get a total (only
                // for the current ordinal position iPt)
                foreach (CurveItem tmpCurve in pane.CurveList)
                {
                    // make sure the curve is a Line type
                    if (tmpCurve is LineItem && tmpCurve.IsVisible)
                    {
                        curVal = PointPair.Missing;
                        // For non-ordinal curves, find a matching base value (must match exactly)
                        if (curve.IsOverrideOrdinal || !baseAxis._scale.IsAnyOrdinal)
                        {
                            IPointList points = tmpCurve.Points;

                            for (int i = 0; i < points.Count; i++)
                            {
                                if (points[i].X == baseVal)
                                {
                                    curVal = points[i].Y;
                                    break;
                                }
                            }
                        }
                        // otherwise, it's an ordinal type so use the value at the same ordinal position
                        else if (iPt < tmpCurve.Points.Count)
                        {
                            // For line types, the Y axis is always the value axis
                            curVal = tmpCurve.Points[iPt].Y;
                        }

                        // if the current value is missing, then the rest of the stack is missing
                        if (curVal == PointPair.Missing)
                        {
                            stack = PointPair.Missing;
                        }

                        // if the current curve is the target curve, save the values
                        if (tmpCurve == curve)
                        {
                            lowVal = stack;
                            hiVal  = (curVal == PointPair.Missing || stack == PointPair.Missing) ?
                                     PointPair.Missing : stack + curVal;
                        }

                        // sum all the curves to a single total.  This includes both positive and
                        // negative values (unlike the bar stack type).
                        stack = (curVal == PointPair.Missing || stack == PointPair.Missing) ?
                                PointPair.Missing : stack + curVal;
                    }
                }

                if (baseVal == PointPair.Missing || lowVal == PointPair.Missing ||
                    hiVal == PointPair.Missing)
                {
                    return(false);
                }
                else
                {
                    return(true);
                }
            }
            // otherwise, the curve is not a stacked type (not a stacked bar or stacked line)
            else
            {
                if ((!(curve is HiLowBarItem)) && (!(curve is ErrorBarItem)))
                {
                    lowVal = 0;
                }
                else
                {
                    lowVal = curve.Points[iPt].LowValue;
                }

                if (baseAxis is XAxis || baseAxis is X2Axis)
                {
                    hiVal = curve.Points[iPt].Y;
                }
                else
                {
                    hiVal = curve.Points[iPt].X;
                }
            }

            // Special Exception: Bars on log scales should always plot from the Min value upwards,
            // since they can never be zero
            if (curve is BarItem && valueAxis._scale.IsLog && lowVal == 0)
            {
                lowVal = valueAxis._scale._min;
            }

            if (baseVal == PointPair.Missing || hiVal == PointPair.Missing ||
                (lowVal == PointPair.Missing && (curve is ErrorBarItem ||
                                                 curve is HiLowBarItem)))
            {
                return(false);
            }
            else
            {
                return(true);
            }
        }
Example #7
0
 /// <summary>
 /// Get the user scale values associate with a particular point of a
 /// particular curve.</summary>
 /// <remarks>The main purpose of this method is to handle
 /// stacked bars, in which case the stacked values are returned rather
 /// than the individual data values.
 /// </remarks>
 /// <param name="curve">A <see cref="CurveItem"/> object of interest.</param>
 /// <param name="iPt">The zero-based point index for the point of interest.</param>
 /// <param name="baseVal">A <see cref="Double"/> value representing the value
 /// for the independent axis.</param>
 /// <param name="lowVal">A <see cref="Double"/> value representing the lower
 /// value for the dependent axis.</param>
 /// <param name="hiVal">A <see cref="Double"/> value representing the upper
 /// value for the dependent axis.</param>
 /// <returns>true if the data point is value, false for
 /// <see cref="PointPairBase.Missing"/>, invalid, etc. data.</returns>
 public bool GetValues(CurveItem curve, int iPt, out double baseVal,
                       out double lowVal, out double hiVal)
 {
     return(GetValues(_pane, curve, iPt, out baseVal,
                      out lowVal, out hiVal));
 }