/// <summary> /// Creates a bitmap of the graph. /// </summary> /// <param name="Settings">Graph settings.</param> /// <param name="States">State objects that contain graph-specific information about its inner states. /// These can be used in calls back to the graph object to make actions on the generated graph.</param> /// <returns>Bitmap</returns> public abstract SKImage CreateBitmap(GraphSettings Settings, out object[] States);
/// <summary> /// Creates a bitmap of the graph. /// </summary> /// <param name="Settings">Graph settings.</param> /// <param name="States">State object(s) that contain graph-specific information about its inner states. /// These can be used in calls back to the graph object to make actions on the generated graph.</param> /// <returns>Bitmap</returns> public override SKImage CreateBitmap(GraphSettings Settings, out object[] States) { using (SKSurface Surface = SKSurface.Create(Settings.Width, Settings.Height, SKImageInfo.PlatformColorType, SKAlphaType.Premul)) { SKCanvas Canvas = Surface.Canvas; States = new object[0]; Canvas.Clear(Settings.BackgroundColor); int x1, y1, x2, y2, x3, y3, w, h; x1 = Settings.MarginLeft; x2 = Settings.Width - Settings.MarginRight; y1 = Settings.MarginTop; y2 = Settings.Height - Settings.MarginBottom; IVector YLabels = GetLabels(ref this.minY, ref this.maxY, this.y, Settings.ApproxNrLabelsY, out LabelType YLabelType); SKPaint Font = new SKPaint() { FilterQuality = SKFilterQuality.High, HintingLevel = SKPaintHinting.Full, SubpixelText = true, IsAntialias = true, Style = SKPaintStyle.Fill, Color = Settings.AxisColor, Typeface = SKTypeface.FromFamilyName(Settings.FontName, SKTypefaceStyle.Normal), TextSize = (float)Settings.LabelFontSize }; float Size; double MaxSize = 0; if (this.showYAxis) { foreach (IElement Label in YLabels.ChildElements) { Size = Font.MeasureText(LabelString(Label, YLabelType)); if (Size > MaxSize) { MaxSize = Size; } } } x3 = (int)Math.Ceiling(x1 + MaxSize) + Settings.MarginLabel; IVector XLabels = GetLabels(ref this.minX, ref this.maxX, this.x, Settings.ApproxNrLabelsX, out LabelType XLabelType); MaxSize = 0; if (this.showXAxis) { foreach (IElement Label in XLabels.ChildElements) { Size = Font.MeasureText(LabelString(Label, XLabelType)); if (Size > MaxSize) { MaxSize = Size; } } } y3 = (int)Math.Floor(y2 - MaxSize) - Settings.MarginLabel; w = x2 - x3; h = y3 - y1; SKPaint AxisBrush = new SKPaint() { FilterQuality = SKFilterQuality.High, IsAntialias = true, Style = SKPaintStyle.Fill, Color = Settings.AxisColor }; SKPaint GridBrush = new SKPaint() { FilterQuality = SKFilterQuality.High, IsAntialias = true, Style = SKPaintStyle.Fill, Color = Settings.GridColor }; SKPaint AxisPen = new SKPaint() { FilterQuality = SKFilterQuality.High, IsAntialias = true, Style = SKPaintStyle.Stroke, Color = Settings.AxisColor, StrokeWidth = Settings.AxisWidth }; SKPaint GridPen = new SKPaint() { FilterQuality = SKFilterQuality.High, IsAntialias = true, Style = SKPaintStyle.Stroke, Color = Settings.GridColor, StrokeWidth = Settings.GridWidth }; double OrigoX; double OrigoY; if (this.minX.AssociatedSet is IAbelianGroup AgX) { OrigoX = Scale(new ObjectVector(AgX.AdditiveIdentity), this.minX, this.maxX, x3, w)[0]; } else { OrigoX = 0; } if (this.minY.AssociatedSet is IAbelianGroup AgY) { OrigoY = Scale(new ObjectVector(AgY.AdditiveIdentity), this.minY, this.maxY, y3, -h)[0]; } else { OrigoY = 0; } DrawingArea DrawingArea = new DrawingArea(this.minX, this.maxX, this.minY, this.maxY, x3, y3, w, -h, (float)OrigoX, (float)OrigoY); double[] LabelYY = DrawingArea.ScaleY(YLabels); int i = 0; float f; string s; foreach (IElement Label in YLabels.ChildElements) { Size = Font.MeasureText(s = LabelString(Label, YLabelType)); f = (float)LabelYY[i++]; if (this.showGrid) { if (Label is DoubleNumber && ((DoubleNumber)Label).Value == 0) { Canvas.DrawLine(x3, f, x2, f, AxisPen); } else { Canvas.DrawLine(x3, f, x2, f, GridPen); } } if (this.showYAxis) { f += (float)Settings.LabelFontSize * 0.5f; Canvas.DrawText(s, x3 - Size - Settings.MarginLabel, f, Font); } } double[] LabelXX = DrawingArea.ScaleX(XLabels); i = 0; foreach (IElement Label in XLabels.ChildElements) { Size = Font.MeasureText(s = LabelString(Label, XLabelType)); f = (float)LabelXX[i++]; if (this.showGrid) { if (Label is DoubleNumber && ((DoubleNumber)Label).Value == 0) { Canvas.DrawLine(f, y1, f, y3, AxisPen); } else { Canvas.DrawLine(f, y1, f, y3, GridPen); } } if (this.showXAxis) { f -= Size * 0.5f; if (f < x3) { f = x3; } else if (f + Size > x3 + w) { f = x3 + w - Size; } Canvas.DrawText(s, f, y3 + Settings.MarginLabel + (float)Settings.LabelFontSize, Font); } } IEnumerator <IVector> ex = this.x.GetEnumerator(); IEnumerator <IVector> ey = this.y.GetEnumerator(); IEnumerator <object[]> eParameters = this.parameters.GetEnumerator(); IEnumerator <DrawCallback> eCallbacks = this.callbacks.GetEnumerator(); SKPoint[] Points; SKPoint[] PrevPoints = null; object[] PrevParameters = null; DrawCallback PrevCallback = null; while (ex.MoveNext() && ey.MoveNext() && eParameters.MoveNext() && eCallbacks.MoveNext()) { Points = DrawingArea.Scale(ex.Current, ey.Current); if (PrevCallback != null && eCallbacks.Current.Target.GetType() == PrevCallback.Target.GetType()) { eCallbacks.Current(Canvas, Points, eParameters.Current, PrevPoints, PrevParameters, DrawingArea); } else { eCallbacks.Current(Canvas, Points, eParameters.Current, null, null, DrawingArea); } PrevPoints = Points; PrevParameters = eParameters.Current; PrevCallback = eCallbacks.Current; } SKImage Result = Surface.Snapshot(); Font.Dispose(); AxisBrush.Dispose(); GridBrush.Dispose(); GridPen.Dispose(); AxisPen.Dispose(); States = new object[] { DrawingArea }; return(Result); } }
/// <summary> /// Creates a bitmap of the graph. /// </summary> /// <param name="Settings">Graph settings.</param> /// <returns>Bitmap</returns> public SKImage CreateBitmap(GraphSettings Settings) { return(this.CreateBitmap(Settings, out object[] States)); }
/// <summary> /// Creates a bitmap of the graph. /// </summary> /// <param name="Settings">Graph settings.</param> /// <param name="States">State object(s) that contain graph-specific information about its inner states. /// These can be used in calls back to the graph object to make actions on the generated graph.</param> /// <returns>Bitmap</returns> public override SKImage CreateBitmap(GraphSettings Settings, out object[] States) { States = new object[0]; return(this.bitmap); }