/// <summary> /// Initializes a new instance of the <see cref="LineItem"/> class. /// The Copy Constructor /// </summary> /// <param name="rhs"> /// The <see cref="LineItem"/> object from which to copy /// </param> public LineItem(LineItem rhs) : base(rhs) { this._symbol = new Symbol(rhs.Symbol); this._line = new Line(rhs.Line); }
/// <summary> /// Add a curve (<see cref="CurveItem"/> object) to the plot with the given data points (<see cref="IPointList"/>) and properties. This is simplified /// way to add curves without knowledge of the /// <see cref="CurveList"/> class. An alternative is to use the <see cref="Graph.CurveList"/> Add() method. /// </summary> /// <param name="label"> /// The text label (string) for the curve that will be used as a <see cref="Legend"/> entry. /// </param> /// <param name="points"> /// A <see cref="IPointList"/> of double precision value pairs that define the X and Y values for this curve /// </param> /// <param name="color"> /// The color to used for the curve line, symbols, etc. /// </param> /// <param name="symbolType"> /// A symbol type (<see cref="SymbolType"/>) that will be used for this curve. /// </param> /// <returns> /// A <see cref="CurveItem"/> class for the newly created curve. This can then be used to access all of the curve properties that are not defined as /// arguments to the /// <see cref="AddCurve(string,IPointList,Color,SymbolType)"/> method. /// </returns> public LineItem AddCurve(string label, IPointList points, Color color, SymbolType symbolType) { LineItem curve = new LineItem(label, points, color, symbolType); this._curveList.Add(curve); return curve; }
/// <summary> /// Draw this <see cref="CurveItem"/> to the specified <see cref="Graphics"/> /// device as a symbol at each defined point. The routine only draws the symbols; the lines are draw by the /// <see cref="Line.DrawCurve"/> 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> /// <param name="isSelected"> /// Indicates that the <see cref="Symbol"/> should be drawn with attributes from the <see cref="Selection"/> class. /// </param> public void Draw(Graphics g, GraphPane pane, LineItem curve, float scaleFactor, bool isSelected) { Symbol source = this; if (isSelected) { source = Selection.Symbol; } int tmpX, tmpY; int minX = (int)pane.Chart.Rect.Left; int maxX = (int)pane.Chart.Rect.Right; int minY = (int)pane.Chart.Rect.Top; int maxY = (int)pane.Chart.Rect.Bottom; // (Dale-a-b) we'll set an element to true when it has been drawn bool[,] isPixelDrawn = new bool[maxX + 1, maxY + 1]; double curX, curY, lowVal; IPointList points = curve.Points; if (points != null && (this._border.IsVisible || this._fill.IsVisible)) { SmoothingMode sModeSave = g.SmoothingMode; if (this._isAntiAlias) { g.SmoothingMode = SmoothingMode.HighQuality; } // For the sake of speed, go ahead and create a solid brush and a pen // If it's a gradient fill, it will be created on the fly for each symbol // SolidBrush brush = new SolidBrush( this.fill.Color ); using (Pen pen = source._border.GetPen(pane, scaleFactor)) using (GraphicsPath path = this.MakePath(g, scaleFactor)) { RectangleF rect = path.GetBounds(); using (Brush brush = source.Fill.MakeBrush(rect)) { ValueHandler valueHandler = new ValueHandler(pane, false); Scale xScale = curve.GetXAxis(pane).Scale; Scale yScale = curve.GetYAxis(pane).Scale; bool xIsLog = xScale.IsLog; bool yIsLog = yScale.IsLog; bool xIsOrdinal = xScale.IsAnyOrdinal; double xMin = xScale.Min; double xMax = xScale.Max; // Loop over each defined point for (int i = 0; i < points.Count; i++) { // Get the user scale values for the current point // use the valueHandler only for stacked types if (pane.LineType == LineType.Stack) { valueHandler.GetValues(curve, i, out curX, out lowVal, out curY); } // otherwise, just access the values directly. Avoiding the valueHandler for // non-stacked types is an optimization to minimize overhead in case there are // a large number of points. else { curX = points[i].X; if (curve is StickItem) { curY = points[i].Z; } else { curY = points[i].Y; } } // Any value set to double max is invalid and should be skipped // This is used for calculated values that are out of range, divide // by zero, etc. // Also, any value <= zero on a log scale is invalid if (curX != PointPairBase.Missing && curY != PointPairBase.Missing && !double.IsNaN(curX) && !double.IsNaN(curY) && !double.IsInfinity(curX) && !double.IsInfinity(curY) && (curX > 0 || !xIsLog) && (!yIsLog || curY > 0.0) && (xIsOrdinal || (curX >= xMin && curX <= xMax))) { // Transform the user scale values to pixel locations tmpX = (int)xScale.Transform(curve.IsOverrideOrdinal, i, curX); tmpY = (int)yScale.Transform(curve.IsOverrideOrdinal, i, curY); // Maintain an array of "used" pixel locations to avoid duplicate drawing operations if (tmpX >= minX && tmpX <= maxX && tmpY >= minY && tmpY <= maxY) { // guard against the zoom-in case if (isPixelDrawn[tmpX, tmpY]) { continue; } isPixelDrawn[tmpX, tmpY] = true; } // If the fill type for this symbol is a Gradient by value type, // the make a brush corresponding to the appropriate current value if (this._fill.IsGradientValueType || this._border._gradientFill.IsGradientValueType) { using (Brush tBrush = this._fill.MakeBrush(rect, points[i])) using (Pen tPen = this._border.GetPen(pane, scaleFactor, points[i])) this.DrawSymbol(g, tmpX, tmpY, path, tPen, tBrush); } else { // Otherwise, the brush is already defined // Draw the symbol at the specified pixel location this.DrawSymbol(g, tmpX, tmpY, path, pen, brush); } } } } } g.SmoothingMode = sModeSave; } }
/// <summary> /// Add a curve (<see cref="CurveItem"/> object) to the plot with the given data points (double arrays) and properties. This is simplified way to add /// curves without knowledge of the /// <see cref="CurveList"/> class. An alternative is to use the <see cref="Graph.CurveList"/> Add() method. /// </summary> /// <param name="label"> /// The text label (string) for the curve that will be used as a <see cref="Legend"/> entry. /// </param> /// <param name="x"> /// An array of double precision X values (the independent values) that define the curve. /// </param> /// <param name="y"> /// An array of double precision Y values (the dependent values) that define the curve. /// </param> /// <param name="color"> /// The color to used for the curve line, symbols, etc. /// </param> /// <param name="symbolType"> /// A symbol type (<see cref="SymbolType"/>) that will be used for this curve. /// </param> /// <returns> /// A <see cref="CurveItem"/> class for the newly created curve. This can then be used to access all of the curve properties that are not defined as /// arguments to the /// <see cref="AddCurve(string,double[],double[],Color,SymbolType)"/> method. /// </returns> public LineItem AddCurve(string label, double[] x, double[] y, Color color, SymbolType symbolType) { LineItem curve = new LineItem(label, x, y, color, symbolType); this._curveList.Add(curve); return curve; }
/// <summary>The render graph.</summary> private void RenderGraph() { GraphPane graphPane = this.graph.GraphPane; Random rand = new Random(DateTime.Now.Millisecond); var usedColors = new HashSet<string>(); int count = 0; foreach (var pair in this._graphData) { Journey j = pair.Key; string period = StringUtil.GetPeriodString(j.DepartureDate, j.ReturnDate); string colorHex; do { colorHex = string.Format("#{0:X6}", rand.Next(0x1000000) & 0x5F5F5F); } while (usedColors.Contains(colorHex)); usedColors.Add(colorHex); Color curveColor = ColorTranslator.FromHtml(colorHex); LineItem curve = new LineItem(period, pair.Value, curveColor, SymbolType.Square); var curveTarget = count++ == 0 ? graphPane.CurveList : this._hiddenCurves; curveTarget.Add(curve); curve.Tag = new DatePeriod(j.DepartureDate, j.ReturnDate); curve.Line.Width = 2; foreach (ListViewItem item in this.lvTravelPeriod.Items) { var travelDate = item.Tag as DatePeriod; if (travelDate != null && travelDate.StartDate == j.DepartureDate && travelDate.EndDate == j.ReturnDate) { item.ForeColor = curveColor; break; } } } graphPane.AxisChange(); }