internal override void Draw( ChartGraphics g, int[] xValues, int[] stackValues, int lastPlotType ) { g.Pen = new Pen(color, lineWidth); g.Color = color; int ax, ay, nx, ny; // Get X positions if ( xVal1 == Int64.MinValue ) ax = g.MinX; else if ( xVal1 == Int64.MaxValue ) ax = g.MaxX; else ax = g.GetX( xVal1 ); if ( xVal2 == Int64.MinValue ) nx = g.MinX; else if ( xVal2 == Int64.MaxValue ) nx = g.MaxX; else nx = g.GetX( xVal2 ); // Get Y positions if ( yVal1 == Double.MinValue ) ay = g.MinY; else if ( yVal1 == Double.MaxValue ) ay = g.MaxY; else ay = g.GetY( yVal1 ); if ( yVal2 == Double.MinValue ) ny = g.MinY; else if ( yVal2 == Double.MaxValue ) ny = g.MaxY; else ny = g.GetY( yVal2 ); // Draw the area if ( visible ) { if ( ny > ay ) g.FillRect( ax, ay, nx, ny ); else g.FillRect( ax, ny, nx, ay ); } // Set the stackvalues // Always use the y value of the second specified point to stack on if ( yVal2 != Double.MaxValue ) for (int i = 0; i < stackValues.Length; i++) if ( xValues[i] < ax || xValues[i] > nx ) stackValues[i] = 0; else stackValues[i] = ny; }
internal override void Draw( ChartGraphics g, int[] xValues, int[] stackValues, int lastPlotType ) { g.Pen = new Pen(color, lineWidth); g.Color = color; double [] values = source.Values; int ax = 0, ay = 0, py; int nx = 0, ny = 0; for (int i = 0; i < xValues.Length; i++) { py = 0; nx = xValues[i]; ny = g.GetY(values[i]); if ( !Double.IsNaN(values[i]) ) { if ( stacked ) { py = stackValues[i]; ny += ( stackValues[i] == Int32.MinValue ? Int32.MinValue : stackValues[i] ); } if ( visible ) { if (nx > ax + 1) // More than one pixel hop, draw intermediate pixels too { // For each pixel between nx and ax, calculate the y, plot the line int co = (ny - ay) / (nx - ax); int j = (ax > 0 ? ax : 1 ); // Skip 0 for (j = ax; j <= nx; j++) if ( ay != Int32.MinValue && ny != Int32.MinValue ) g.DrawLine( j, py, j, ( co * (j - ax) + ay) ); } else if ( nx != 0 && py != Int32.MinValue && ny != Int32.MinValue ) g.DrawLine( nx, py, nx, ny ); } } // Special case with NaN doubles stackValues[i] = ny; ax = nx; ay = ny; } }
internal override void Draw( ChartGraphics g, int[] xValues, int[] stackValues, int lastPlotType ) { PlotDef stack = null; try { if ( lastPlotType == PlotDef.PLOT_LINE ) stack = new Line( source, color, true, visible ); else if ( lastPlotType == PlotDef.PLOT_AREA ) stack = new Area( source, color, true, visible ); stack.Draw( g, xValues, stackValues, lastPlotType ); } catch (Exception) { throw new RrdException( "Could not stack source: " + sourceName ); } }
private void PlotChartGrid( ChartGraphics chartGraph ) { Graphics g = chartGraph.Graphics; Font ft = normal_font; //defaultPen.Color = Color.Black; int lux = x_offset + chart_lpadding; int luy = y_offset + CHART_UPADDING; bool minorX = graphDef.MinorGridX; bool minorY = graphDef.MinorGridY; bool majorX = graphDef.MajorGridX; bool majorY = graphDef.MajorGridY; Color minColor = graphDef.MinorGridColor; Color majColor = graphDef.MajorGridColor; // Dashed line dashPen.DashStyle = DashStyle.Dot; // Draw basic axis int tmpx = lux + chartWidth; int tmpy = luy + chartHeight; // Draw X axis with arrow defaultPen.Color = graphDef.AxisColor; g.DrawLine( defaultPen, lux - 4, tmpy, tmpx + 4, tmpy ); defaultPen.Color = graphDef.ArrowColor; g.DrawLine( defaultPen, tmpx + 4, tmpy - 3, tmpx + 4, tmpy + 3 ); g.DrawLine( defaultPen, tmpx + 4, tmpy - 3, tmpx + 9, tmpy ); g.DrawLine( defaultPen, tmpx + 4, tmpy + 3, tmpx + 9, tmpy ); // Draw X axis time grid and labels if ( graphDef.GridX ) { TimeMarker[] timeList = tGrid.TimeMarkers; bool labelCentered = tGrid.CenterLabels; long labelGridWidth = tGrid.MajorGridWidth; int pixWidth = 0; if ( labelCentered ) pixWidth = ( chartGraph.GetX( labelGridWidth ) - chartGraph.GetX( 0 ) ); for (int i = 0; i < timeList.Length; i++) { long secTime = timeList[i].Timestamp; int posRel = chartGraph.GetX(secTime); int pos = lux + posRel; string label = timeList[i].Label; stringLength = g.MeasureString(label,ft,1000,sf); if ( posRel >= 0 ) { if ( majorX && timeList[i].IsLabel ) { dashPen.Color = majColor ; g.DrawLine( dashPen, pos, luy, pos, luy + chartHeight ); defaultPen.Color = majColor; g.DrawLine( defaultPen, pos, luy - 2, pos, luy + 2 ); g.DrawLine( defaultPen, pos, luy + chartHeight - 2, pos, luy + chartHeight + 2 ); // Only draw label itself if we are far enough from the side axis // Use extra 2 pixel padding (3 pixels from border total at least) int txtDistance = (int) (stringLength.Width) / 2; if ( labelCentered ) { if ( pos + pixWidth <= lux + chartWidth ) GraphString( g, ft, label, pos + 2 + pixWidth/2 - txtDistance, luy + chartHeight + LINE_PADDING ); } else if ( (pos - lux > txtDistance + 2) && (pos + txtDistance + 2 < lux + chartWidth) ) GraphString( g, ft, label, pos - txtDistance, luy + chartHeight + LINE_PADDING ); } else if ( minorX ) { dashPen.Color = minColor; g.DrawLine( dashPen, pos, luy, pos, luy + chartHeight ); defaultPen.Color = minColor; g.DrawLine( defaultPen, pos, luy - 1, pos, luy + 1 ); g.DrawLine( defaultPen, pos, luy + chartHeight - 1, pos, luy + chartHeight + 1 ); } } } } // Draw Y axis value grid and labels valueFormat.SetScaling( true, false ); // always scale the label values if ( graphDef.GridY ) { ValueMarker[] valueList = vGrid.ValueMarkers; for (int i = 0; i < valueList.Length; i++) { int valRel = chartGraph.GetY( valueList[i].Value ); valueFormat.SetFormat( valueList[i].Value, 2, 0 ); string label = (valueFormat.ScaledValue + " " + valueFormat.Prefix).Trim(); stringLength = g.MeasureString(label,ft,1000,sf); if ( majorY && valueList[i].IsMajor ) { dashPen.Color = majColor; g.DrawLine( dashPen, graphOriginX, graphOriginY - valRel, graphOriginX + chartWidth, graphOriginY - valRel ); defaultPen.Color = majColor; // solid dashes at ends of lines g.DrawLine( defaultPen, graphOriginX - 2, graphOriginY - valRel, graphOriginX + 2, graphOriginY - valRel ); g.DrawLine( defaultPen, graphOriginX + chartWidth - 2, graphOriginY - valRel, graphOriginX + chartWidth + 2, graphOriginY - valRel ); GraphString( g, ft, label, graphOriginX - (int)(stringLength.Width) - 7, graphOriginY - valRel - (int)(nfont_height/2) ); } else if ( minorY ) { dashPen.Color = minColor; g.DrawLine( dashPen, graphOriginX, graphOriginY - valRel, graphOriginX + chartWidth, graphOriginY - valRel ); defaultPen.Color = minColor; g.DrawLine( defaultPen, graphOriginX - 1, graphOriginY - valRel, graphOriginX + 1, graphOriginY - valRel ); g.DrawLine( defaultPen, graphOriginX + chartWidth - 1, graphOriginY - valRel, graphOriginX + chartWidth + 1, graphOriginY - valRel ); } } } }
private void PlotChart( Graphics graphics ) { int lux = x_offset + chart_lpadding; int luy = y_offset + CHART_UPADDING; //defaultBrush.Color = Color.White; //defaultPen.Color = Color.Black; //if ( graphDef.Background == null ) //{ defaultBrush.Color = graphDef.CanvasColor; graphics.FillRectangle(defaultBrush, lux, luy, chartWidth, chartHeight ); //} // Draw the chart area frame defaultPen.Color = graphDef.FrameColor; graphics.DrawRectangle(defaultPen, lux, luy, chartWidth, chartHeight ); double val; double[] tmpSeries = new double[numPoints]; GridRange range = graphDef.GridRange; bool rigid = ( range != null ? range.Rigid : false ); double lowerValue = ( range != null ? range.LowerValue : Double.MaxValue ); double upperValue = ( range != null ? range.UpperValue : Double.MinValue ); // For autoscale, detect lower and upper limit of values PlotDef[] plotDefs = graphDef.PlotDefs; for ( int i = 0; i < plotDefs.Length; i++ ) { plotDefs[i].SetSource( sources, sourceIndex ); Source src = plotDefs[i].Source; // Only try autoscale when we do not have a rigid grid if ( !rigid && src != null ) { double min = src.GetAggregate( Source.AGG_MINIMUM ); double max = src.GetAggregate( Source.AGG_MAXIMUM ); // If the plotdef is a stack, evaluate ALL previous values to find a possible max if ( plotDefs[i].plotType == PlotDef.PLOT_STACK && i >= 1 ) { if ( plotDefs[i - 1].plotType == PlotDef.PLOT_STACK ) { // Use this source plus stack of previous ones for (int j = 0; j < tmpSeries.Length; j++) { val = tmpSeries[j] + plotDefs[i].GetValue(j, timestamps); if ( val < lowerValue ) lowerValue = val; if ( val > upperValue ) upperValue = val; tmpSeries[j] = val; } } else { // Use this source plus the previous one for (int j = 0; j < tmpSeries.Length; j++) { val = plotDefs[i - 1].GetValue(j, timestamps) + plotDefs[i].GetValue(j, timestamps); if ( val < lowerValue ) lowerValue = val; if ( val > upperValue ) upperValue = val; tmpSeries[j] = val; } } } else // Only use min/max of a single datasource { if ( min < lowerValue ) lowerValue = min; if ( max > upperValue ) upperValue = max; } } } vGrid = new ValueGrid( range, lowerValue, upperValue, graphDef.ValueAxis, graphDef.BaseValue ); tGrid = new TimeGrid( graphDef.StartTime, (graphDef.EndTime != 0? graphDef.EndTime : calculatedEndTime), graphDef.TimeAxis, graphDef.FirstDayOfWeek ); lowerValue = vGrid.LowerValue; upperValue = vGrid.UpperValue; // Use a special graph 'object' that takes care of resizing and reversing y coordinates ChartGraphics g = new ChartGraphics( graphics ); g.SetDimensions( chartWidth, chartHeight ); g.SetXRange( tGrid.StartTime, tGrid.EndTime ); g.SetYRange( lowerValue, upperValue ); // Set the chart origin point double diff = 1.0d; if ( lowerValue < 0 ) diff = 1.0d - ( lowerValue / ( -upperValue + lowerValue )); graphOriginX = lux; graphOriginY = (int) (luy + chartHeight * diff); // If the grid is behind the plots, draw it first if ( !graphDef.FrontGrid ) PlotChartGrid( g ); // Use AA if necessary if ( graphDef.AntiAliasing ) graphics.SmoothingMode = SmoothingMode.AntiAlias; // Prepare clipping area and origin graphics.SetClip(new System.Drawing.Rectangle( lux, luy, chartWidth, chartHeight)); graphics.TranslateTransform( graphOriginX, graphOriginY ); int lastPlotType = PlotDef.PLOT_LINE; int[] parentSeries = new int[numPoints]; // Pre calculate x positions of the corresponding timestamps int[] xValues = new int[timestamps.Length]; for (int i = 0; i < timestamps.Length; i++) xValues[i] = g.GetX(timestamps[i]); // Draw all graphed values for (int i = 0; i < plotDefs.Length; i++) { plotDefs[i].Draw( g, xValues, parentSeries, lastPlotType ); if(plotDefs[i].PlotType != PlotDef.PLOT_STACK) { lastPlotType = plotDefs[i].PlotType; } } // Reset clipping area, origin and AA settings graphics.TranslateTransform( (float)-graphOriginX, (float)-graphOriginY ); graphics.SetClip(new System.Drawing.Rectangle(0, 0, imgWidth, imgHeight)); graphics.SmoothingMode = SmoothingMode.None; // If the grid is in front of the plots, draw it now if ( graphDef.FrontGrid ) PlotChartGrid( g ); }