/// <summary> /// Initializes a new instance of the <see cref="ZoomState"/> class. /// Construct a <see cref="ZoomState"/> object from the scale ranges settings contained in the specified <see cref="GraphPane"/>. /// </summary> /// <param name="pane"> /// The <see cref="GraphPane"/> from which to obtain the scale range values. /// </param> /// <param name="type"> /// A <see cref="StateType"/> enumeration that indicates whether this saved RequestState is from a pan or zoom. /// </param> public ZoomState(GraphPane pane, StateType type) { this._xAxis = new ScaleState(pane.XAxis); this._x2Axis = new ScaleState(pane.X2Axis); this._yAxis = new ScaleStateList(pane.YAxisList); this._y2Axis = new ScaleStateList(pane.Y2AxisList); this._type = type; }
/// <summary> /// Initializes a new instance of the <see cref="ValueHandler"/> class. /// Basic constructor that saves a reference to the parent /// <see cref="GraphPane"/> object. /// </summary> /// <param name="pane"> /// The parent <see cref="GraphPane"/> object. /// </param> /// <param name="initialize"> /// A <see cref="bool"/> flag to indicate whether or not the drawing variables should be initialized. Initialization is not required if this is part of /// a ZedGraph internal draw operation (i.e., its in the middle of a call to <see cref="GraphPane.Draw"/>). Otherwise, you should initialize to make /// sure the drawing variables are configured. true to do an initialization, false otherwise. /// </param> public ValueHandler(GraphPane pane, bool initialize) { this._pane = pane; if (initialize) { // just create a dummy image, which results in a full draw operation using (Image image = pane.GetImage()) { } } }
/// <summary> /// Gets a flag indicating if the X axis is the independent axis for this <see cref="CurveItem"/> /// </summary> /// <param name="pane"> /// The parent <see cref="GraphPane"/> of this <see cref="CurveItem"/>. /// </param> /// <value> /// true if the X axis is independent, false otherwise /// </value> /// <returns> /// The <see cref="bool"/>. /// </returns> internal override bool IsXIndependent(GraphPane pane) { return true; }
/// <summary> /// Draw a legend key entry for this <see cref="LineItem"/> at the specified location /// </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="rect"> /// The <see cref="RectangleF"/> struct that specifies the location for the legend key /// </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 override void DrawLegendKey(Graphics g, GraphPane pane, RectangleF rect, float scaleFactor) { // Draw a sample curve to the left of the label text int xMid = (int)(rect.Left + rect.Width / 2.0F); int yMid = (int)(rect.Top + rect.Height / 2.0F); // RectangleF rect2 = rect; // rect2.Y = yMid; // rect2.Height = rect.Height / 2.0f; this._line.Fill.Draw(g, rect); this._line.DrawSegment(g, pane, rect.Left, yMid, rect.Right, yMid, scaleFactor); // Draw a sample symbol to the left of the label text this._symbol.DrawSymbol(g, pane, xMid, yMid, scaleFactor, false, null); }
/// <summary> /// Draw the this <see cref="CurveItem"/> to the specified <see cref="Graphics"/> /// device. The format (stair-step or line) of the curve is defined by the <see cref="StepType"/> property. The routine only draws the line segments; /// the symbols are drawn by the /// <see cref="Symbol.Draw"/> method. This method is normally only called by the Draw method of the /// <see cref="CurveItem"/> 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="LineItem"/> representing this curve. /// </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 DrawCurveOriginal(Graphics g, GraphPane pane, CurveItem curve, float scaleFactor) { Line source = this; if (curve.IsSelected) { source = Selection.Line; } float tmpX, tmpY, lastX = float.MaxValue, lastY = float.MaxValue; double curX, curY, lowVal; PointPair curPt, lastPt = new PointPair(); bool lastBad = true; IPointList points = curve.Points; ValueHandler valueHandler = new ValueHandler(pane, false); Axis yAxis = curve.GetYAxis(pane); Axis xAxis = curve.GetXAxis(pane); bool xIsLog = xAxis._scale.IsLog; bool yIsLog = yAxis._scale.IsLog; float minX = pane.Chart.Rect.Left; float maxX = pane.Chart.Rect.Right; float minY = pane.Chart.Rect.Top; float maxY = pane.Chart.Rect.Bottom; using (Pen pen = source.GetPen(pane, scaleFactor)) { if (points != null && !this._color.IsEmpty && this.IsVisible) { // bool lastOut = false; bool isOut; // Loop over each point in the curve for (int i = 0; i < points.Count; i++) { curPt = points[i]; if (pane.LineType == LineType.Stack) { if (!valueHandler.GetValues(curve, i, out curX, out lowVal, out curY)) { curX = PointPairBase.Missing; curY = PointPairBase.Missing; } } else { curX = curPt.X; curY = curPt.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 == PointPairBase.Missing || curY == PointPairBase.Missing || double.IsNaN(curX) || double.IsNaN(curY) || double.IsInfinity(curX) || double.IsInfinity(curY) || (xIsLog && curX <= 0.0) || (yIsLog && curY <= 0.0)) { // If the point is invalid, then make a linebreak only if IsIgnoreMissing is false // LastX and LastY are always the last valid point, so this works out lastBad = lastBad || !pane.IsIgnoreMissing; isOut = true; } else { // Transform the current point from user scale units to // screen coordinates tmpX = xAxis.Scale.Transform(curve.IsOverrideOrdinal, i, curX); tmpY = yAxis.Scale.Transform(curve.IsOverrideOrdinal, i, curY); isOut = (tmpX < minX && lastX < minX) || (tmpX > maxX && lastX > maxX) || (tmpY < minY && lastY < minY) || (tmpY > maxY && lastY > maxY); if (!lastBad) { try { // GDI+ plots the data wrong and/or throws an exception for // outrageous coordinates, so we do a sanity check here if (lastX > 5000000 || lastX < -5000000 || lastY > 5000000 || lastY < -5000000 || tmpX > 5000000 || tmpX < -5000000 || tmpY > 5000000 || tmpY < -5000000) { this.InterpolatePoint(g, pane, curve, lastPt, scaleFactor, pen, lastX, lastY, tmpX, tmpY); } else if (!isOut) { if (!curve.IsSelected && this._gradientFill.IsGradientValueType) { using (Pen tPen = this.GetPen(pane, scaleFactor, lastPt)) { if (this.StepType == StepType.NonStep) { g.DrawLine(tPen, lastX, lastY, tmpX, tmpY); } else if (this.StepType == StepType.ForwardStep) { g.DrawLine(tPen, lastX, lastY, tmpX, lastY); g.DrawLine(tPen, tmpX, lastY, tmpX, tmpY); } else if (this.StepType == StepType.RearwardStep) { g.DrawLine(tPen, lastX, lastY, lastX, tmpY); g.DrawLine(tPen, lastX, tmpY, tmpX, tmpY); } else if (this.StepType == StepType.ForwardSegment) { g.DrawLine(tPen, lastX, lastY, tmpX, lastY); } else { g.DrawLine(tPen, lastX, tmpY, tmpX, tmpY); } } } else { if (this.StepType == StepType.NonStep) { g.DrawLine(pen, lastX, lastY, tmpX, tmpY); } else if (this.StepType == StepType.ForwardStep) { g.DrawLine(pen, lastX, lastY, tmpX, lastY); g.DrawLine(pen, tmpX, lastY, tmpX, tmpY); } else if (this.StepType == StepType.RearwardStep) { g.DrawLine(pen, lastX, lastY, lastX, tmpY); g.DrawLine(pen, lastX, tmpY, tmpX, tmpY); } else if (this.StepType == StepType.ForwardSegment) { g.DrawLine(pen, lastX, lastY, tmpX, lastY); } else if (this.StepType == StepType.RearwardSegment) { g.DrawLine(pen, lastX, tmpY, tmpX, tmpY); } } } } catch { this.InterpolatePoint(g, pane, curve, lastPt, scaleFactor, pen, lastX, lastY, tmpX, tmpY); } } lastPt = curPt; lastX = tmpX; lastY = tmpY; lastBad = false; // lastOut = isOut; } } } } }
/// <summary> /// Close off a <see cref="GraphicsPath"/> that defines a curve /// </summary> /// <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="LineItem"/> representing this curve. /// </param> /// <param name="arrPoints"> /// An array of <see cref="PointF"/> values in screen pixel coordinates representing the current curve. /// </param> /// <param name="count"> /// The number of points contained in the "arrPoints" parameter. /// </param> /// <param name="yMin"> /// The Y axis value location where the X axis crosses. /// </param> /// <param name="path"> /// The <see cref="GraphicsPath"/> class that represents the curve. /// </param> public void CloseCurve(GraphPane pane, CurveItem curve, PointF[] arrPoints, int count, double yMin, GraphicsPath path) { // For non-stacked lines, the fill area is just the area between the curve and the X axis if (pane.LineType != LineType.Stack) { // Determine the current value for the bottom of the curve (usually the Y value where // the X axis crosses) float yBase; Axis yAxis = curve.GetYAxis(pane); yBase = yAxis.Scale.Transform(yMin); // Add three points to the path to move from the end of the curve (as defined by // arrPoints) to the X axis, from there to the start of the curve at the X axis, // and from there back up to the beginning of the curve. path.AddLine(arrPoints[count - 1].X, arrPoints[count - 1].Y, arrPoints[count - 1].X, yBase); path.AddLine(arrPoints[count - 1].X, yBase, arrPoints[0].X, yBase); path.AddLine(arrPoints[0].X, yBase, arrPoints[0].X, arrPoints[0].Y); } // For stacked line types, the fill area is the area between this curve and the curve below it else { PointF[] arrPoints2; int count2; float tension = this._isSmooth ? this._smoothTension : 0f; // Find the next lower curve in the curveList that is also a LineItem type, and use // its smoothing properties for the lower side of the filled area. int index = pane.CurveList.IndexOf(curve); if (index > 0) { CurveItem tmpCurve; for (int i = index - 1; i >= 0; i--) { tmpCurve = pane.CurveList[i]; if (tmpCurve is LineItem) { tension = ((LineItem)tmpCurve).Line.IsSmooth ? ((LineItem)tmpCurve).Line.SmoothTension : 0f; break; } } } // Build another points array consisting of the low points (which are actually the points for // the curve below the current curve) this.BuildLowPointsArray(pane, curve, out arrPoints2, out count2); // Add the new points to the GraphicsPath path.AddCurve(arrPoints2, 0, count2 - 2, tension); } }
/// <summary> /// Build an array of <see cref="PointF"/> values (pixel coordinates) that represents the low values for the current curve. /// </summary> /// <remarks> /// Note that this drawing routine ignores <see cref="PointPairBase.Missing"/> /// values, but it does not "break" the line to indicate values are missing. /// </remarks> /// <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="LineItem"/> representing this curve. /// </param> /// <param name="arrPoints"> /// An array of <see cref="PointF"/> values in pixel coordinates representing the current curve. /// </param> /// <param name="count"> /// The number of points contained in the "arrPoints" parameter. /// </param> /// <returns> /// true for a successful points array build, false for data problems /// </returns> public bool BuildLowPointsArray(GraphPane pane, CurveItem curve, out PointF[] arrPoints, out int count) { arrPoints = null; count = 0; IPointList points = curve.Points; if (this.IsVisible && !this.Color.IsEmpty && points != null) { int index = 0; float curX, curY, lastX = 0, lastY = 0; double x, y, hiVal; ValueHandler valueHandler = new ValueHandler(pane, false); // Step type plots get twice as many points. Always add three points so there is // room to close out the curve for area fills. arrPoints = new PointF[(this._stepType == StepType.NonStep ? 1 : 2) * (pane.LineType == LineType.Stack ? 2 : 1) * points.Count + 1]; // Loop backwards over all points in the curve // In this case an array of points was already built forward by BuildPointsArray(). // This time we build backwards to complete a loop around the area between two curves. for (int i = points.Count - 1; i >= 0; i--) { // Make sure the current point is valid if (!points[i].IsInvalid) { // Get the user scale values for the current point valueHandler.GetValues(curve, i, out x, out y, out hiVal); if (x == PointPairBase.Missing || y == PointPairBase.Missing) { continue; } // Transform the user scale values to pixel locations Axis xAxis = curve.GetXAxis(pane); curX = xAxis.Scale.Transform(curve.IsOverrideOrdinal, i, x); Axis yAxis = curve.GetYAxis(pane); curY = yAxis.Scale.Transform(curve.IsOverrideOrdinal, i, y); // Add the pixel value pair into the points array // Two points are added for step type curves // ignore step-type setting for smooth curves if (this._isSmooth || index == 0 || this.StepType == StepType.NonStep) { arrPoints[index].X = curX; arrPoints[index].Y = curY; } else if (this.StepType == StepType.ForwardStep) { arrPoints[index].X = curX; arrPoints[index].Y = lastY; index++; arrPoints[index].X = curX; arrPoints[index].Y = curY; } else if (this.StepType == StepType.RearwardStep) { arrPoints[index].X = lastX; arrPoints[index].Y = curY; index++; arrPoints[index].X = curX; arrPoints[index].Y = curY; } lastX = curX; lastY = curY; index++; } } // Make sure there is at least one valid point if (index == 0) { return false; } // Add an extra point at the end, since the smoothing algorithm requires it arrPoints[index] = arrPoints[index - 1]; index++; count = index; return true; } return false; }
/// <summary> /// This method just handles the case where one or more of the coordinates are outrageous, or GDI+ threw an exception. This method attempts to correct /// the outrageous coordinates by interpolating them to a point (along the original line) that lies at the edge of the ChartRect so that GDI+ will handle /// it properly. GDI+ will throw an exception, or just plot the data incorrectly if the coordinates are too large (empirically, this appears to be when /// the coordinate value is greater than 5,000,000 or less than -5,000,000). Although you typically would not see coordinates like this, if you /// repeatedly zoom in on a ZedGraphControl, eventually all your points will be way outside the bounds of the plot. /// </summary> /// <param name="g"> /// The g. /// </param> /// <param name="pane"> /// The pane. /// </param> /// <param name="curve"> /// The curve. /// </param> /// <param name="lastPt"> /// The last Pt. /// </param> /// <param name="scaleFactor"> /// The scale Factor. /// </param> /// <param name="pen"> /// The pen. /// </param> /// <param name="lastX"> /// The last X. /// </param> /// <param name="lastY"> /// The last Y. /// </param> /// <param name="tmpX"> /// The tmp X. /// </param> /// <param name="tmpY"> /// The tmp Y. /// </param> private void InterpolatePoint( Graphics g, GraphPane pane, CurveItem curve, PointPair lastPt, float scaleFactor, Pen pen, float lastX, float lastY, float tmpX, float tmpY) { try { RectangleF chartRect = pane.Chart._rect; // try to interpolate values bool lastIn = chartRect.Contains(lastX, lastY); bool curIn = chartRect.Contains(tmpX, tmpY); // If both points are outside the ChartRect, make a new point that is on the LastX/Y // side of the ChartRect, and fall through to the code that handles lastIn == true if (!lastIn) { float newX, newY; if (Math.Abs(lastX) > Math.Abs(lastY)) { newX = lastX < 0 ? chartRect.Left : chartRect.Right; newY = lastY + (tmpY - lastY) * (newX - lastX) / (tmpX - lastX); } else { newY = lastY < 0 ? chartRect.Top : chartRect.Bottom; newX = lastX + (tmpX - lastX) * (newY - lastY) / (tmpY - lastY); } lastX = newX; lastY = newY; } if (!curIn) { float newX, newY; if (Math.Abs(tmpX) > Math.Abs(tmpY)) { newX = tmpX < 0 ? chartRect.Left : chartRect.Right; newY = tmpY + (lastY - tmpY) * (newX - tmpX) / (lastX - tmpX); } else { newY = tmpY < 0 ? chartRect.Top : chartRect.Bottom; newX = tmpX + (lastX - tmpX) * (newY - tmpY) / (lastY - tmpY); } tmpX = newX; tmpY = newY; } /* if ( this.StepType == StepType.ForwardStep ) { g.DrawLine( pen, lastX, lastY, tmpX, lastY ); g.DrawLine( pen, tmpX, lastY, tmpX, tmpY ); } else if ( this.StepType == StepType.RearwardStep ) { g.DrawLine( pen, lastX, lastY, lastX, tmpY ); g.DrawLine( pen, lastX, tmpY, tmpX, tmpY ); } else // non-step g.DrawLine( pen, lastX, lastY, tmpX, tmpY ); */ if (!curve.IsSelected && this._gradientFill.IsGradientValueType) { using (Pen tPen = this.GetPen(pane, scaleFactor, lastPt)) { if (this.StepType == StepType.NonStep) { g.DrawLine(tPen, lastX, lastY, tmpX, tmpY); } else if (this.StepType == StepType.ForwardStep) { g.DrawLine(tPen, lastX, lastY, tmpX, lastY); g.DrawLine(tPen, tmpX, lastY, tmpX, tmpY); } else if (this.StepType == StepType.RearwardStep) { g.DrawLine(tPen, lastX, lastY, lastX, tmpY); g.DrawLine(tPen, lastX, tmpY, tmpX, tmpY); } else if (this.StepType == StepType.ForwardSegment) { g.DrawLine(tPen, lastX, lastY, tmpX, lastY); } else { g.DrawLine(tPen, lastX, tmpY, tmpX, tmpY); } } } else { if (this.StepType == StepType.NonStep) { g.DrawLine(pen, lastX, lastY, tmpX, tmpY); } else if (this.StepType == StepType.ForwardStep) { g.DrawLine(pen, lastX, lastY, tmpX, lastY); g.DrawLine(pen, tmpX, lastY, tmpX, tmpY); } else if (this.StepType == StepType.RearwardStep) { g.DrawLine(pen, lastX, lastY, lastX, tmpY); g.DrawLine(pen, lastX, tmpY, tmpX, tmpY); } else if (this.StepType == StepType.ForwardSegment) { g.DrawLine(pen, lastX, lastY, tmpX, lastY); } else if (this.StepType == StepType.RearwardSegment) { g.DrawLine(pen, lastX, tmpY, tmpX, tmpY); } } } catch { } }
/// <summary> /// Draw a tic mark at the specified single position. This includes the inner, outer, cross and opposite tic marks as required. /// </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="pen"> /// Graphic <see cref="Pen"/> with which to draw the tic mark. /// </param> /// <param name="pixVal"> /// The pixel location of the tic mark on this /// <see cref="Axis"/> /// </param> /// <param name="topPix"> /// The pixel value of the top of the axis border /// </param> /// <param name="shift"> /// The number of pixels to shift this axis, based on the value of <see cref="Axis.Cross"/>. A positive value is into the ChartRect relative to the /// default axis position. /// </param> /// <param name="scaledTic"> /// The scaled size of a minor tic, in pixel units /// </param> internal void Draw(Graphics g, GraphPane pane, Pen pen, float pixVal, float topPix, float shift, float scaledTic) { // draw the outside tic if (this.IsOutside) { g.DrawLine(pen, pixVal, shift, pixVal, shift + scaledTic); } // draw the cross tic if (this._isCrossOutside) { g.DrawLine(pen, pixVal, 0.0f, pixVal, scaledTic); } // draw the inside tic if (this.IsInside) { g.DrawLine(pen, pixVal, shift, pixVal, shift - scaledTic); } // draw the inside cross tic if (this._isCrossInside) { g.DrawLine(pen, pixVal, 0.0f, pixVal, -scaledTic); } // draw the opposite tic if (this.IsOpposite) { g.DrawLine(pen, pixVal, topPix, pixVal, topPix + scaledTic); } }
/// <summary> /// Go through the list of <see cref="PointPair"/> data values for this <see cref="CurveItem"/> /// and determine the minimum and maximum values in the data. /// </summary> /// <param name="xMin"> /// The minimum X value in the range of data /// </param> /// <param name="xMax"> /// The maximum X value in the range of data /// </param> /// <param name="yMin"> /// The minimum Y value in the range of data /// </param> /// <param name="yMax"> /// The maximum Y value in the range of data /// </param> /// <param name="ignoreInitial"> /// ignoreInitial is a boolean value that affects the data range that is considered for the automatic scale ranging (see /// <see cref="GraphPane.IsIgnoreInitial"/>). If true, then initial data points where the Y value is zero are not included when automatically /// determining the scale <see cref="Scale.Min"/>, /// <see cref="Scale.Max"/>, and <see cref="Scale.MajorStep"/> size. All data after the first non-zero Y value are included. /// </param> /// <param name="isBoundedRanges"> /// Determines if the auto-scaled axis ranges will subset the data points based on any manually set scale range values. /// </param> /// <param name="pane"> /// A reference to the <see cref="GraphPane"/> object that is the parent or owner of this object. /// </param> /// <seealso cref="GraphPane.IsBoundedRanges"/> public virtual void GetRange( out double xMin, out double xMax, out double yMin, out double yMax, bool ignoreInitial, bool isBoundedRanges, GraphPane pane) { // The lower and upper bounds of allowable data for the X values. These // values allow you to subset the data values. If the X range is bounded, then // the resulting range for Y will reflect the Y values for the points within the X // bounds. double xLBound = double.MinValue; double xUBound = double.MaxValue; double yLBound = double.MinValue; double yUBound = double.MaxValue; // initialize the values to outrageous ones to start xMin = yMin = double.MaxValue; xMax = yMax = double.MinValue; Axis yAxis = this.GetYAxis(pane); Axis xAxis = this.GetXAxis(pane); if (yAxis == null || xAxis == null) { return; } if (isBoundedRanges) { xLBound = xAxis._scale._lBound; xUBound = xAxis._scale._uBound; yLBound = yAxis._scale._lBound; yUBound = yAxis._scale._uBound; } bool isZIncluded = this.IsZIncluded(pane); bool isXIndependent = this.IsXIndependent(pane); bool isXLog = xAxis.Scale.IsLog; bool isYLog = yAxis.Scale.IsLog; bool isXOrdinal = xAxis.Scale.IsAnyOrdinal; bool isYOrdinal = yAxis.Scale.IsAnyOrdinal; bool isZOrdinal = (isXIndependent ? yAxis : xAxis).Scale.IsAnyOrdinal; // Loop over each point in the arrays // foreach ( PointPair point in this.Points ) for (int i = 0; i < this.Points.Count; i++) { PointPair point = this.Points[i]; double curX = isXOrdinal ? i + 1 : point.X; double curY = isYOrdinal ? i + 1 : point.Y; double curZ = isZOrdinal ? i + 1 : point.Z; bool outOfBounds = curX < xLBound || curX > xUBound || curY < yLBound || curY > yUBound || (isZIncluded && isXIndependent && (curZ < yLBound || curZ > yUBound)) || (isZIncluded && !isXIndependent && (curZ < xLBound || curZ > xUBound)) || (curX <= 0 && isXLog) || (curY <= 0 && isYLog); // ignoreInitial becomes false at the first non-zero // Y value if (ignoreInitial && curY != 0 && curY != PointPairBase.Missing) { ignoreInitial = false; } if (!ignoreInitial && !outOfBounds && curX != PointPairBase.Missing && curY != PointPairBase.Missing) { if (curX < xMin) { xMin = curX; } if (curX > xMax) { xMax = curX; } if (curY < yMin) { yMin = curY; } if (curY > yMax) { yMax = curY; } if (isZIncluded && isXIndependent && curZ != PointPairBase.Missing) { if (curZ < yMin) { yMin = curZ; } if (curZ > yMax) { yMax = curZ; } } else if (isZIncluded && curZ != PointPairBase.Missing) { if (curZ < xMin) { xMin = curZ; } if (curZ > xMax) { xMax = curZ; } } } } }
/// <summary> /// Determine the coords for the rectangle associated with a specified point for this <see cref="CurveItem"/> /// </summary> /// <param name="pane"> /// The <see cref="GraphPane"/> to which this curve belongs /// </param> /// <param name="i"> /// The index of the point of interest /// </param> /// <param name="coords"> /// A list of coordinates that represents the "rect" for this point (used in an html AREA tag) /// </param> /// <returns> /// true if it's a valid point, false otherwise /// </returns> public abstract bool GetCoords(GraphPane pane, int i, out string coords);
/// <summary> /// Calculate the width of each bar, depending on the actual bar type /// </summary> /// <param name="pane"> /// The pane. /// </param> /// <returns> /// The width for an individual bar, in pixel units /// </returns> public float GetBarWidth(GraphPane pane) { // Total axis width = // npts * ( nbars * ( bar + bargap ) - bargap + clustgap ) // cg * bar = cluster gap // npts = max number of points in any curve // nbars = total number of curves that are of type IsBar // bar = bar width // bg * bar = bar gap // therefore: // totwidth = npts * ( nbars * (bar + bg*bar) - bg*bar + cg*bar ) // totwidth = bar * ( npts * ( nbars * ( 1 + bg ) - bg + cg ) ) // solve for bar float barWidth; if (this is ErrorBarItem) { barWidth = ((ErrorBarItem)this).Bar.Symbol.Size * pane.CalcScaleFactor(); } // else if ( this is HiLowBarItem && pane._barSettings.Type != BarType.ClusterHiLow ) // barWidth = (float) ( ((HiLowBarItem)this).Bar.GetBarWidth( pane, // ((HiLowBarItem)this).BaseAxis(pane), pane.CalcScaleFactor() ) ); // barWidth = (float) ( ((HiLowBarItem)this).Bar.Size * // pane.CalcScaleFactor() ); else { // BarItem or LineItem // For stacked bar types, the bar width will be based on a single bar float numBars = 1.0F; if (pane._barSettings.Type == BarType.Cluster) { numBars = pane.CurveList.NumClusterableBars; } float denom = numBars * (1.0F + pane._barSettings.MinBarGap) - pane._barSettings.MinBarGap + pane._barSettings.MinClusterGap; if (denom <= 0) { denom = 1; } barWidth = pane.BarSettings.GetClusterWidth() / denom; } if (barWidth <= 0) { return 1; } return barWidth; }
/// <summary> /// Draw a legend key entry for this <see cref="CurveItem"/> at the specified location. This abstract base method passes through to /// <see cref="BarItem.DrawLegendKey"/> or /// <see cref="LineItem.DrawLegendKey"/> to do the rendering. /// </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="rect"> /// The <see cref="RectangleF"/> struct that specifies the location for the legend key /// </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 abstract void DrawLegendKey(Graphics g, GraphPane pane, RectangleF rect, float scaleFactor);
/// <summary> /// Do all rendering associated with this <see cref="CurveItem"/> to the specified /// <see cref="Graphics"/> device. This method is normally only called by the Draw method of the parent <see cref="CurveList"/> /// collection 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="pos"> /// The ordinal position of the current <see cref="Bar"/> /// curve. /// </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 abstract void Draw(Graphics g, GraphPane pane, int pos, float scaleFactor);
/// <summary> /// Returns a reference to the <see cref="Axis"/> object that is the "base" (independent axis) from which the values are drawn. /// </summary> /// <param name="pane"> /// The pane. /// </param> /// <remarks> /// This property is determined by the value of <see cref="BarSettings.Base"/> for /// <see cref="BarItem"/>, <see cref="ErrorBarItem"/>, and <see cref="HiLowBarItem"/> /// types. It is always the X axis for regular <see cref="LineItem"/> types. Note that the <see cref="BarSettings.Base"/> setting can override the /// <see cref="IsY2Axis"/> and <see cref="YAxisIndex"/> settings for bar types (this is because all the bars that are clustered together must share the /// same base axis). /// </remarks> /// <seealso cref="BarBase"/> /// <seealso cref="ValueAxis"/> /// <returns> /// The <see cref="Axis"/>. /// </returns> public virtual Axis BaseAxis(GraphPane pane) { BarBase barBase; if (this is BarItem || this is ErrorBarItem || this is HiLowBarItem) { barBase = pane._barSettings.Base; } else { barBase = this._isX2Axis ? BarBase.X2 : BarBase.X; } if (barBase == BarBase.X) { return pane.XAxis; } if (barBase == BarBase.X2) { return pane.X2Axis; } if (barBase == BarBase.Y) { return pane.YAxis; } return pane.Y2Axis; }
/// <summary> /// Draw the this <see cref="CurveItem"/> to the specified <see cref="Graphics"/> /// device using the specified smoothing property (<see cref="Line.SmoothTension"/>). The routine draws the line segments and the area fill (if any, see /// <see cref="FillType"/>; the symbols are drawn by the <see cref="Symbol.Draw"/> method. This method is normally only called by the Draw method of /// the /// <see cref="CurveItem"/> object. Note that the <see cref="StepType"/> property is ignored for smooth lines (e.g., when <see cref="Line.IsSmooth"/> /// is true). /// </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="LineItem"/> representing this curve. /// </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 DrawSmoothFilledCurve(Graphics g, GraphPane pane, CurveItem curve, float scaleFactor) { Line source = this; if (curve.IsSelected) { source = Selection.Line; } PointF[] arrPoints; int count; IPointList points = curve.Points; if (this.IsVisible && !this.Color.IsEmpty && points != null && this.BuildPointsArray(pane, curve, out arrPoints, out count) && count > 2) { float tension = this._isSmooth ? this._smoothTension : 0f; // Fill the curve if needed if (this.Fill.IsVisible) { Axis yAxis = curve.GetYAxis(pane); using (GraphicsPath path = new GraphicsPath(FillMode.Winding)) { path.AddCurve(arrPoints, 0, count - 2, tension); double yMin = yAxis._scale._min < 0 ? 0.0 : yAxis._scale._min; this.CloseCurve(pane, curve, arrPoints, count, yMin, path); RectangleF rect = path.GetBounds(); using (Brush brush = source._fill.MakeBrush(rect)) { if (pane.LineType == LineType.Stack && yAxis.Scale._min < 0 && this.IsFirstLine(pane, curve)) { float zeroPix = yAxis.Scale.Transform(0); RectangleF tRect = pane.Chart._rect; tRect.Height = zeroPix - tRect.Top; if (tRect.Height > 0) { Region reg = g.Clip; g.SetClip(tRect); g.FillPath(brush, path); g.SetClip(pane.Chart._rect); } } else { g.FillPath(brush, path); } // brush.Dispose(); } // restore the zero line if needed (since the fill tends to cover it up) yAxis.FixZeroLine(g, pane, scaleFactor, rect.Left, rect.Right); } } // If it's a smooth curve, go ahead and render the path. Otherwise, use the // standard drawcurve method just in case there are missing values. if (this._isSmooth) { using (Pen pen = this.GetPen(pane, scaleFactor)) { // Stroke the curve g.DrawCurve(pen, arrPoints, 0, count - 2, tension); // pen.Dispose(); } } else { this.DrawCurve(g, pane, curve, scaleFactor); } } }
/// <summary> /// Render the <see cref="Line"/>'s as vertical sticks (from a <see cref="StickItem"/>) to the specified <see cref="Graphics"/> device. /// </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"/> representing this curve. /// </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 DrawSticks(Graphics g, GraphPane pane, CurveItem curve, float scaleFactor) { Line source = this; if (curve.IsSelected) { source = Selection.Line; } Axis yAxis = curve.GetYAxis(pane); Axis xAxis = curve.GetXAxis(pane); float basePix = yAxis.Scale.Transform(0.0); using (Pen pen = source.GetPen(pane, scaleFactor)) { for (int i = 0; i < curve.Points.Count; i++) { PointPair pt = curve.Points[i]; if (pt.X != PointPairBase.Missing && pt.Y != PointPairBase.Missing && !double.IsNaN(pt.X) && !double.IsNaN(pt.Y) && !double.IsInfinity(pt.X) && !double.IsInfinity(pt.Y) && (!xAxis._scale.IsLog || pt.X > 0.0) && (!yAxis._scale.IsLog || pt.Y > 0.0)) { float pixY = yAxis.Scale.Transform(curve.IsOverrideOrdinal, i, pt.Y); float pixX = xAxis.Scale.Transform(curve.IsOverrideOrdinal, i, pt.X); if (pixX >= pane.Chart._rect.Left && pixX <= pane.Chart._rect.Right) { if (pixY > pane.Chart._rect.Bottom) { pixY = pane.Chart._rect.Bottom; } if (pixY < pane.Chart._rect.Top) { pixY = pane.Chart._rect.Top; } if (!curve.IsSelected && this._gradientFill.IsGradientValueType) { using (Pen tPen = this.GetPen(pane, scaleFactor, pt)) g.DrawLine(tPen, pixX, pixY, pixX, basePix); } else { g.DrawLine(pen, pixX, pixY, pixX, basePix); } } } } } }
/// <summary> /// The get pen. /// </summary> /// <param name="pane"> /// The pane. /// </param> /// <param name="scaleFactor"> /// The scale factor. /// </param> /// <returns> /// The <see cref="Pen"/>. /// </returns> internal Pen GetPen(GraphPane pane, float scaleFactor) { return new Pen(this._color, pane.ScaledPenWidth(this._penWidth, scaleFactor)); }
/// <summary> /// The is first line. /// </summary> /// <param name="pane"> /// The pane. /// </param> /// <param name="curve"> /// The curve. /// </param> /// <returns> /// The <see cref="bool"/>. /// </returns> private bool IsFirstLine(GraphPane pane, CurveItem curve) { CurveList curveList = pane.CurveList; for (int j = 0; j < curveList.Count; j++) { CurveItem tCurve = curveList[j]; if (tCurve is LineItem && tCurve.IsY2Axis == curve.IsY2Axis && tCurve.YAxisIndex == curve.YAxisIndex) { return tCurve == curve; } } return false; }
/// <summary> /// Setup the Transform Matrix to handle drawing of this <see cref="Y2Axis"/> /// </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="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 override void SetTransformMatrix(Graphics g, GraphPane pane, float scaleFactor) { // Move the origin to the BottomRight of the ChartRect, which is the left // side of the Y2 axis (facing from the label side) g.TranslateTransform(pane.Chart._rect.Right, pane.Chart._rect.Bottom); // rotate so this axis is in the left-right direction g.RotateTransform(-90); }
/// <summary> /// Build an array of <see cref="PointF"/> values (pixel coordinates) that represents the current curve. Note that this drawing routine ignores /// <see cref="PointPairBase.Missing"/> /// values, but it does not "break" the line to indicate values are missing. /// </summary> /// <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="LineItem"/> representing this curve. /// </param> /// <param name="arrPoints"> /// An array of <see cref="PointF"/> values in pixel coordinates representing the current curve. /// </param> /// <param name="count"> /// The number of points contained in the "arrPoints" parameter. /// </param> /// <returns> /// true for a successful points array build, false for data problems /// </returns> public bool BuildPointsArray(GraphPane pane, CurveItem curve, out PointF[] arrPoints, out int count) { arrPoints = null; count = 0; IPointList points = curve.Points; if (this.IsVisible && !this.Color.IsEmpty && points != null) { int index = 0; float curX, curY, lastX = 0, lastY = 0; double x, y, lowVal; ValueHandler valueHandler = new ValueHandler(pane, false); // Step type plots get twice as many points. Always add three points so there is // room to close out the curve for area fills. arrPoints = new PointF[(this._stepType == StepType.NonStep ? 1 : 2) * points.Count + 1]; // Loop over all points in the curve for (int i = 0; i < points.Count; i++) { // make sure that the current point is valid if (!points[i].IsInvalid) { // 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 x, out lowVal, out y); } // 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 { x = points[i].X; y = points[i].Y; } if (x == PointPairBase.Missing || y == PointPairBase.Missing) { continue; } // Transform the user scale values to pixel locations Axis xAxis = curve.GetXAxis(pane); curX = xAxis.Scale.Transform(curve.IsOverrideOrdinal, i, x); Axis yAxis = curve.GetYAxis(pane); curY = yAxis.Scale.Transform(curve.IsOverrideOrdinal, i, y); if (curX < -1000000 || curY < -1000000 || curX > 1000000 || curY > 1000000) { continue; } // Add the pixel value pair into the points array // Two points are added for step type curves // ignore step-type setting for smooth curves if (this._isSmooth || index == 0 || this.StepType == StepType.NonStep) { arrPoints[index].X = curX; arrPoints[index].Y = curY; } else if (this.StepType == StepType.ForwardStep || this.StepType == StepType.ForwardSegment) { arrPoints[index].X = curX; arrPoints[index].Y = lastY; index++; arrPoints[index].X = curX; arrPoints[index].Y = curY; } else if (this.StepType == StepType.RearwardStep || this.StepType == StepType.RearwardSegment) { arrPoints[index].X = lastX; arrPoints[index].Y = curY; index++; arrPoints[index].X = curX; arrPoints[index].Y = curY; } lastX = curX; lastY = curY; index++; } } // Make sure there is at least one valid point if (index == 0) { return false; } // Add an extra point at the end, since the smoothing algorithm requires it arrPoints[index] = arrPoints[index - 1]; index++; count = index; return true; } return false; }
/* override internal bool IsCrossed( GraphPane pane ) { return !this.crossAuto && this.cross > pane.YAxis.Min && this.cross < pane.YAxis.Max; } */ /// <summary> /// Gets the "Cross" axis that corresponds to this axis. /// </summary> /// <remarks> /// The cross axis is the axis which determines the of this Axis when the /// <see cref="Axis.Cross">Axis.Cross</see> property is used. The cross axis for any <see cref="XAxis"/> or <see cref="X2Axis"/> /// is always the primary <see cref="YAxis"/>, and the cross axis for any <see cref="YAxis"/> or <see cref="Y2Axis"/> is always the primary /// <see cref="XAxis"/>. /// </remarks> /// <param name="pane"> /// A reference to the <see cref="GraphPane"/> object that is the parent or owner of this object. /// </param> /// <returns> /// The <see cref="Axis"/>. /// </returns> public override Axis GetCrossAxis(GraphPane pane) { return pane.YAxis; }
/// <summary> /// Do all rendering associated with this <see cref="Line"/> to the specified /// <see cref="Graphics"/> device. This method is normally only called by the Draw method of the parent <see cref="LineItem"/> 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="LineItem"/> representing this curve. /// </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, GraphPane pane, CurveItem curve, float scaleFactor) { // If the line is being shown, draw it if (this.IsVisible) { // How to handle fill vs nofill? // if ( isSelected ) // GraphPane.Default.SelectedLine. SmoothingMode sModeSave = g.SmoothingMode; if (this._isAntiAlias) { g.SmoothingMode = SmoothingMode.HighQuality; } if (curve is StickItem) { this.DrawSticks(g, pane, curve, scaleFactor); } else if (this.IsSmooth || this.Fill.IsVisible) { this.DrawSmoothFilledCurve(g, pane, curve, scaleFactor); } else { this.DrawCurve(g, pane, curve, scaleFactor); } g.SmoothingMode = sModeSave; } }
/// <summary> /// Setup the Transform Matrix to handle drawing of this <see cref="XAxis"/> /// </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="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 override void SetTransformMatrix(Graphics g, GraphPane pane, float scaleFactor) { // Move the origin to the BottomLeft of the ChartRect, which is the left // side of the X axis (facing from the label side) g.TranslateTransform(pane.Chart._rect.Left, pane.Chart._rect.Bottom); }
/// <summary> /// Do all rendering associated with this <see cref="LineItem"/> to the specified /// <see cref="Graphics"/> device. This method is normally only called by the Draw method of the parent <see cref="CurveList"/> /// collection 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="pos"> /// The ordinal position of the current <see cref="Bar"/> /// curve. /// </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 override void Draw(Graphics g, GraphPane pane, int pos, float scaleFactor) { if (this._isVisible) { this.Line.Draw(g, pane, this, scaleFactor); this.Symbol.Draw(g, pane, this, scaleFactor, this.IsSelected); } }
/// <summary> /// Calculate the "shift" size, in pixels, in order to shift the axis from its default location to the value specified by /// <see cref="Axis.Cross"/>. /// </summary> /// <param name="pane"> /// A reference to the <see cref="GraphPane"/> object that is the parent or owner of this object. /// </param> /// <returns> /// The shift amount measured in pixels /// </returns> internal override float CalcCrossShift(GraphPane pane) { double effCross = this.EffectiveCrossValue(pane); if (!this._crossAuto) { return pane.YAxis.Scale.Transform(effCross) - pane.YAxis.Scale._maxPix; } return 0; }
/// <summary> /// Determine the coords for the rectangle associated with a specified point for this <see cref="CurveItem"/> /// </summary> /// <param name="pane"> /// The <see cref="GraphPane"/> to which this curve belongs /// </param> /// <param name="i"> /// The index of the point of interest /// </param> /// <param name="coords"> /// A list of coordinates that represents the "rect" for this point (used in an html AREA tag) /// </param> /// <returns> /// true if it's a valid point, false otherwise /// </returns> public override bool GetCoords(GraphPane pane, int i, out string coords) { coords = string.Empty; if (i < 0 || i >= this._points.Count) { return false; } PointPair pt = this._points[i]; if (pt.IsInvalid) { return false; } double x, y, z; ValueHandler valueHandler = new ValueHandler(pane, false); valueHandler.GetValues(this, i, out x, out z, out y); Axis yAxis = this.GetYAxis(pane); Axis xAxis = this.GetXAxis(pane); PointF pixPt = new PointF(xAxis.Scale.Transform(this._isOverrideOrdinal, i, x), yAxis.Scale.Transform(this._isOverrideOrdinal, i, y)); if (!pane.Chart.Rect.Contains(pixPt)) { return false; } float halfSize = this._symbol.Size * pane.CalcScaleFactor(); coords = string.Format("{0:f0},{1:f0},{2:f0},{3:f0}", pixPt.X - halfSize, pixPt.Y - halfSize, pixPt.X + halfSize, pixPt.Y + halfSize); return true; }
/// <summary> /// Determines if this <see cref="Axis"/> object is a "primary" one. /// </summary> /// <remarks> /// The primary axes are the <see cref="XAxis"/> (always), the first /// <see cref="YAxis"/> in the <see cref="GraphPane.YAxisList"/> /// (<see cref="CurveItem.YAxisIndex"/> = 0), and the first /// <see cref="Y2Axis"/> in the <see cref="GraphPane.Y2AxisList"/> /// (<see cref="CurveItem.YAxisIndex"/> = 0). Note that /// <see cref="GraphPane.YAxis"/> and <see cref="GraphPane.Y2Axis"/> /// always reference the primary axes. /// </remarks> /// <param name="pane"> /// A reference to the <see cref="GraphPane"/> object that is the parent or owner of this object. /// </param> /// <returns> /// true for a primary <see cref="Axis"/> (for the <see cref="XAxis"/>, this is always true), false otherwise /// </returns> internal override bool IsPrimary(GraphPane pane) { return this == pane.XAxis; }
/// <summary> /// Gets a flag indicating if the Z data range should be included in the axis scaling calculations. /// </summary> /// <param name="pane"> /// The parent <see cref="GraphPane"/> of this <see cref="CurveItem"/>. /// </param> /// <value> /// true if the Z data are included, false otherwise /// </value> /// <returns> /// The <see cref="bool"/>. /// </returns> internal override bool IsZIncluded(GraphPane pane) { return false; }
/// <summary> /// Render a single <see cref="Line"/> segment to the specified /// <see cref="Graphics"/> device. /// </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="x1"> /// The x position of the starting point that defines the line segment in screen pixel units /// </param> /// <param name="y1"> /// The y position of the starting point that defines the line segment in screen pixel units /// </param> /// <param name="x2"> /// The x position of the ending point that defines the line segment in screen pixel units /// </param> /// <param name="y2"> /// The y position of the ending point that defines the line segment in screen pixel units /// </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 DrawSegment(Graphics g, GraphPane pane, float x1, float y1, float x2, float y2, float scaleFactor) { if (this._isVisible && !this.Color.IsEmpty) { using (Pen pen = this.GetPen(pane, scaleFactor)) { g.DrawLine(pen, x1, y1, x2, y2); } } }