Esempio n. 1
0
        /// <summary>
        /// Find the data point that lies closest to the specified mouse (screen) point.
        /// </summary>
        /// <remarks>
        /// This method will search through the specified list of curves to find which point is nearest.  It will only consider points that are within
        /// <see cref="Default.NearestTol"/> pixels of the screen point, and it will only consider <see cref="CurveItem"/>'s that are in
        /// <paramref name="targetCurveList"/>.
        /// </remarks>
        /// <param name="mousePt">
        /// The screen point, in pixel coordinates.
        /// </param>
        /// <param name="targetCurveList">
        /// A <see cref="CurveList"/> object containing a subset of <see cref="CurveItem"/>'s to be searched.
        /// </param>
        /// <param name="nearestCurve">
        /// A reference to the <see cref="CurveItem"/>
        /// instance that contains the closest point.  nearestCurve will be null if no data points are available.
        /// </param>
        /// <param name="iNearest">
        /// The index number of the closest point.  The actual data vpoint will then be <see cref="CurveItem.Points">CurveItem.Points[iNearest]</see>
        /// .  iNearest will be -1 if no data points are available.
        /// </param>
        /// <returns>
        /// true if a point was found and that point lies within
        /// <see cref="Default.NearestTol"/> pixels of the screen point, false otherwise.
        /// </returns>
        public bool FindNearestPoint(PointF mousePt, CurveList targetCurveList, out CurveItem nearestCurve, out int iNearest)
        {
            CurveItem nearestBar = null;
            int iNearestBar = -1;
            nearestCurve = null;
            iNearest = -1;

            // If the point is outside the ChartRect, always return false
            if (!this._chart._rect.Contains(mousePt))
            {
                return false;
            }

            double x, x2;
            double[] y;
            double[] y2;

            // ReverseTransform( mousePt, out x, out y, out y2 );
            this.ReverseTransform(mousePt, out x, out x2, out y, out y2);

            if (!this.AxisRangesValid())
            {
                return false;
            }

            ValueHandler valueHandler = new ValueHandler(this, false);

            // double	yPixPerUnit = chartRect.Height / ( yAxis.Max - yAxis.Min );
            // double	y2PixPerUnit; // = chartRect.Height / ( y2Axis.Max - y2Axis.Min );
            double yPixPerUnitAct, yAct, yMinAct, yMaxAct, xAct;
            double minDist = 1e20;
            double xVal, yVal, dist = 99999, distX, distY;
            double tolSquared = Default.NearestTol * Default.NearestTol;

            int iBar = 0;

            foreach (CurveItem curve in targetCurveList)
            {
                // test for pie first...if it's a pie rest of method superfluous
                if (curve is PieItem && curve.IsVisible)
                {
                    if (((PieItem)curve).SlicePath != null && ((PieItem)curve).SlicePath.IsVisible(mousePt))
                    {
                        nearestBar = curve;
                        iNearestBar = 0;
                    }
                }
                else if (curve.IsVisible)
                {
                    int yIndex = curve.GetYAxisIndex(this);
                    Axis yAxis = curve.GetYAxis(this);
                    Axis xAxis = curve.GetXAxis(this);

                    if (curve.IsY2Axis)
                    {
                        yAct = y2[yIndex];
                        yMinAct = this._y2AxisList[yIndex]._scale._min;
                        yMaxAct = this._y2AxisList[yIndex]._scale._max;
                    }
                    else
                    {
                        yAct = y[yIndex];
                        yMinAct = this._yAxisList[yIndex]._scale._min;
                        yMaxAct = this._yAxisList[yIndex]._scale._max;
                    }

                    yPixPerUnitAct = this._chart._rect.Height / (yMaxAct - yMinAct);

                    double xPixPerUnit = this._chart._rect.Width / (xAxis._scale._max - xAxis._scale._min);
                    xAct = xAxis is XAxis ? x : x2;

                    IPointList points = curve.Points;
                    float barWidth = curve.GetBarWidth(this);
                    double barWidthUserHalf;
                    Axis baseAxis = curve.BaseAxis(this);
                    bool isXBaseAxis = baseAxis is XAxis || baseAxis is X2Axis;
                    if (isXBaseAxis)
                    {
                        barWidthUserHalf = barWidth / xPixPerUnit / 2.0;
                    }
                    else
                    {
                        barWidthUserHalf = barWidth / yPixPerUnitAct / 2.0;
                    }

                    if (points != null)
                    {
                        for (int iPt = 0; iPt < curve.NPts; iPt++)
                        {
                            // xVal is the user scale X value of the current point
                            if (xAxis._scale.IsAnyOrdinal && !curve.IsOverrideOrdinal)
                            {
                                xVal = iPt + 1.0;
                            }
                            else
                            {
                                xVal = points[iPt].X;
                            }

                            // yVal is the user scale Y value of the current point
                            if (yAxis._scale.IsAnyOrdinal && !curve.IsOverrideOrdinal)
                            {
                                yVal = iPt + 1.0;
                            }
                            else
                            {
                                yVal = points[iPt].Y;
                            }

                            if (xVal != PointPairBase.Missing && yVal != PointPairBase.Missing)
                            {
                                if (curve.IsBar || curve is ErrorBarItem || curve is HiLowBarItem || curve is OHLCBarItem
                                    || curve is JapaneseCandleStickItem)
                                {
                                    double baseVal, lowVal, hiVal;
                                    valueHandler.GetValues(curve, iPt, out baseVal, out lowVal, out hiVal);

                                    if (lowVal > hiVal)
                                    {
                                        double tmpVal = lowVal;
                                        lowVal = hiVal;
                                        hiVal = tmpVal;
                                    }

                                    if (isXBaseAxis)
                                    {
                                        double centerVal = valueHandler.BarCenterValue(curve, barWidth, iPt, xVal, iBar);

                                        if (xAct < centerVal - barWidthUserHalf || xAct > centerVal + barWidthUserHalf || yAct < lowVal
                                            || yAct > hiVal)
                                        {
                                            continue;
                                        }
                                    }
                                    else
                                    {
                                        double centerVal = valueHandler.BarCenterValue(curve, barWidth, iPt, yVal, iBar);

                                        if (yAct < centerVal - barWidthUserHalf || yAct > centerVal + barWidthUserHalf || xAct < lowVal
                                            || xAct > hiVal)
                                        {
                                            continue;
                                        }
                                    }

                                    if (nearestBar == null)
                                    {
                                        iNearestBar = iPt;
                                        nearestBar = curve;
                                    }
                                }
                                else if (xVal >= xAxis._scale._min && xVal <= xAxis._scale._max && yVal >= yMinAct && yVal <= yMaxAct)
                                {
                                    if (curve is LineItem && this._lineType == LineType.Stack)
                                    {
                                        double zVal;
                                        valueHandler.GetValues(curve, iPt, out xVal, out zVal, out yVal);
                                    }

                                    distX = (xVal - xAct) * xPixPerUnit;
                                    distY = (yVal - yAct) * yPixPerUnitAct;
                                    dist = distX * distX + distY * distY;

                                    if (dist >= minDist)
                                    {
                                        continue;
                                    }

                                    minDist = dist;
                                    iNearest = iPt;
                                    nearestCurve = curve;
                                }
                            }
                        }

                        if (curve.IsBar)
                        {
                            iBar++;
                        }
                    }
                }
            }

            if (nearestCurve is LineItem)
            {
                float halfSymbol = ((LineItem)nearestCurve).Symbol.Size * this.CalcScaleFactor() / 2;
                minDist -= halfSymbol * halfSymbol;
                if (minDist < 0)
                {
                    minDist = 0;
                }
            }

            if (minDist >= tolSquared && nearestBar != null)
            {
                // if no point met the tolerance, but a bar was found, use it
                nearestCurve = nearestBar;
                iNearest = iNearestBar;
                return true;
            }

            if (minDist < tolSquared)
            {
                // Did we find a close point, and is it within the tolerance?
                // (minDist is the square of the distance in pixel units)
                return true;
            }

            return false;
        }
Esempio n. 2
0
        /// <summary>
        /// Create a <see cref="TextObj"/> for each bar in the <see cref="GraphPane"/>.
        /// </summary>
        /// <remarks>
        /// This method will go through the bars, create a label that corresponds to the bar value, and place it on the graph depending on user preferences.
        /// This works for horizontal or vertical bars in clusters or stacks, but only for <see cref="BarItem"/> types.  This method does not apply to
        /// <see cref="ErrorBarItem"/> or <see cref="HiLowBarItem"/> objects. Call this method only after calling <see cref="GraphPane.AxisChange()"/>.
        /// </remarks>
        /// <param name="pane">
        /// The GraphPane in which to place the text labels.
        /// </param>
        /// <param name="isBarCenter">
        /// true to center the labels inside the bars, false to place the labels just above the top of the bar.
        /// </param>
        /// <param name="valueFormat">
        /// The double.ToString string format to use for creating the labels.
        /// </param>
        /// <param name="fontFamily">
        /// The string name of the font family to use for the labels
        /// </param>
        /// <param name="fontSize">
        /// The floating point size of the font, in scaled points
        /// </param>
        /// <param name="fontColor">
        /// The color in which to draw the labels
        /// </param>
        /// <param name="isBold">
        /// true for a bold font type, false otherwise
        /// </param>
        /// <param name="isItalic">
        /// true for an italic font type, false otherwise
        /// </param>
        /// <param name="isUnderline">
        /// true for an underline font type, false otherwise
        /// </param>
        public static void CreateBarLabels(
            GraphPane pane, 
            bool isBarCenter, 
            string valueFormat, 
            string fontFamily, 
            float fontSize, 
            Color fontColor, 
            bool isBold, 
            bool isItalic, 
            bool isUnderline)
        {
            bool isVertical = pane.BarSettings.Base == BarBase.X;

            // keep a count of the number of BarItems
            int curveIndex = 0;

            // Get a valuehandler to do some calculations for us
            ValueHandler valueHandler = new ValueHandler(pane, true);

            // Loop through each curve in the list
            foreach (CurveItem curve in pane.CurveList)
            {
                // work with BarItems only
                BarItem bar = curve as BarItem;
                if (bar != null)
                {
                    IPointList points = curve.Points;

                    // ADD JKB 9/21/07
                    // The labelOffset should depend on whether the curve is YAxis or Y2Axis.
                    // JHC - Generalize to any value axis
                    // Make the gap between the bars and the labels = 1.5% of the axis range
                    float labelOffset;

                    Scale scale = curve.ValueAxis(pane).Scale;
                    labelOffset = (float)(scale._max - scale._min) * 0.015f;

                    // Loop through each point in the BarItem
                    for (int i = 0; i < points.Count; i++)
                    {
                        // Get the high, low and base values for the current bar
                        // note that this method will automatically calculate the "effective"
                        // values if the bar is stacked
                        double baseVal, lowVal, hiVal;
                        valueHandler.GetValues(curve, i, out baseVal, out lowVal, out hiVal);

                        // Get the value that corresponds to the center of the bar base
                        // This method figures out how the bars are positioned within a cluster
                        float centerVal = (float)valueHandler.BarCenterValue(bar, bar.GetBarWidth(pane), i, baseVal, curveIndex);

                        // Create a text label -- note that we have to go back to the original point
                        // data for this, since hiVal and lowVal could be "effective" values from a bar stack
                        string barLabelText = (isVertical ? points[i].Y : points[i].X).ToString(valueFormat);

                        // Calculate the position of the label -- this is either the X or the Y coordinate
                        // depending on whether they are horizontal or vertical bars, respectively
                        float position;
                        if (isBarCenter)
                        {
                            position = (float)(hiVal + lowVal) / 2.0f;
                        }
                        else if (hiVal >= 0)
                        {
                            position = (float)hiVal + labelOffset;
                        }
                        else
                        {
                            position = (float)hiVal - labelOffset;
                        }

                        // Create the new TextObj
                        TextObj label;
                        if (isVertical)
                        {
                            label = new TextObj(barLabelText, centerVal, position);
                        }
                        else
                        {
                            label = new TextObj(barLabelText, position, centerVal);
                        }

                        label.FontSpec.Family = fontFamily;

                        // Configure the TextObj

                        // CHANGE JKB 9/21/07
                        // CoordinateFrame should depend on whether curve is YAxis or Y2Axis.
                        label.Location.CoordinateFrame = (isVertical && curve.IsY2Axis) ? CoordType.AxisXY2Scale : CoordType.AxisXYScale;

                        label.FontSpec.Size = fontSize;
                        label.FontSpec.FontColor = fontColor;
                        label.FontSpec.IsItalic = isItalic;
                        label.FontSpec.IsBold = isBold;
                        label.FontSpec.IsUnderline = isUnderline;

                        label.FontSpec.Angle = isVertical ? 90 : 0;
                        label.Location.AlignH = isBarCenter ? AlignH.Center : (hiVal >= 0 ? AlignH.Left : AlignH.Right);
                        label.Location.AlignV = AlignV.Center;
                        label.FontSpec.Border.IsVisible = false;
                        label.FontSpec.Fill.IsVisible = false;

                        // Add the TextObj to the GraphPane
                        pane.GraphObjList.Add(label);
                    }

                    curveIndex++;
                }
            }
        }