public override AxisLimits2D GetLimits() { var limits = new AxisLimits2D(); foreach (var box in boxAndWhiskers) { limits.ExpandX(box.xPosition - box.box.width / 2, box.xPosition + box.box.width / 2); limits.ExpandX(box.xPosition - box.whisker.width / 2, box.xPosition + box.whisker.width / 2); limits.ExpandX(box.xPosition - box.midline.width / 2, box.xPosition + box.midline.width / 2); limits.ExpandY(box.box.min, box.box.max); limits.ExpandY(box.whisker.min, box.whisker.max); limits.ExpandY(box.midline.position, box.midline.position); if (box.points.Count() > 0) //Cannot call Min() or Max() on empty list { limits.ExpandY(box.points.Min(), box.points.Max()); } } return(limits); }
public override AxisLimits2D GetLimits() { var limits = new AxisLimits2D(); foreach (var box in boxAndWhiskers) { double pointSpread = (Math.Abs(box.dataPoints.offsetFraction) + box.dataPoints.spreadFraction) * box.box.width / 2; limits.ExpandX(box.xPosition - pointSpread, box.xPosition + pointSpread); limits.ExpandX(box.xPosition - box.box.width / 2, box.xPosition + box.box.width / 2); limits.ExpandX(box.xPosition - box.whisker.width / 2, box.xPosition + box.whisker.width / 2); limits.ExpandX(box.xPosition - box.midline.width / 2, box.xPosition + box.midline.width / 2); limits.ExpandY(box.box.min, box.box.max); limits.ExpandY(box.whisker.min, box.whisker.max); limits.ExpandY(box.midline.position, box.midline.position); if (box.dataPoints.values.Count() > 0) //Cannot call Min() or Max() on empty list { limits.ExpandY(box.dataPoints.values.Min(), box.dataPoints.values.Max()); } } return(limits); }
public override void Render(Settings settings) { double[] proportions = values.Select(x => x / values.Sum()).ToArray(); int outlineWidth = 1; int sliceOutlineWidth = 0; if (explodedChart) { pen.Color = settings.misc.dataBackgroundColor; outlineWidth = 20; sliceOutlineWidth = 1; } double minAxisScale = Math.Min(settings.xAxisScale, settings.yAxisScale); AxisLimits2D limits = GetLimits(); double centreX = (limits.x1 + limits.x2) / 2; double centreY = (limits.y1 + limits.y2) / 2; double diameter = 2; // Unit circle float diameterPixels = (float)(minAxisScale * diameter); string fontName = Config.Fonts.GetSansFontName(); float fontSize = 12; // record label details and draw them after slices to prevent cover-ups double[] labelXs = new double[values.Length]; double[] labelYs = new double[values.Length]; string[] labelStrings = new string[values.Length]; RectangleF boundingRectangle = new RectangleF((float)settings.GetPixelX(centreX) - diameterPixels / 2, (float)settings.GetPixelY(centreY) - diameterPixels / 2, diameterPixels, diameterPixels); double start = -90; for (int i = 0; i < values.Length; i++) { // determine where the slice is to be drawn double sweep = proportions[i] * 360; double sweepOffset = explodedChart ? -1 : 0; double angle = (Math.PI / 180) * ((sweep + 2 * start) / 2); double xOffset = explodedChart ? 3 * Math.Cos(angle) : 0; double yOffset = explodedChart ? 3 * Math.Sin(angle) : 0; // record where and what to label the slice double sliceLabelR = 0.5 * minAxisScale; labelXs[i] = (boundingRectangle.X + diameterPixels / 2 + xOffset + Math.Cos(angle) * sliceLabelR); labelYs[i] = (boundingRectangle.Y + diameterPixels / 2 + yOffset + Math.Sin(angle) * sliceLabelR); string sliceLabelValue = (showValues) ? $"{values[i]}" : ""; string sliceLabelPercentage = (showPercentages) ? $"{proportions[i] * 100:f1}%" : ""; string sliceLabelName = (showLabels) ? groupNames[i] : ""; labelStrings[i] = $"{sliceLabelValue}\n{sliceLabelPercentage}\n{sliceLabelName}".Trim(); brush.Color = colors[i]; settings.gfxData.FillPie(brush, (int)(boundingRectangle.X + xOffset), (int)(boundingRectangle.Y + yOffset), boundingRectangle.Width, boundingRectangle.Height, (float)start, (float)(sweep + sweepOffset)); if (explodedChart) { pen.Width = sliceOutlineWidth; settings.gfxData.DrawPie(pen, (int)(boundingRectangle.X + xOffset), (int)(boundingRectangle.Y + yOffset), boundingRectangle.Width, boundingRectangle.Height, (float)start, (float)(sweep + sweepOffset)); } start += sweep; } brush.Color = Color.White; var font = new Font(fontName, fontSize); for (int i = 0; i < values.Length; i++) { if (!string.IsNullOrWhiteSpace(labelStrings[i])) { settings.gfxData.DrawString(labelStrings[i], font, brush, (float)labelXs[i], (float)labelYs[i], settings.misc.sfCenterCenter); } } pen.Width = outlineWidth; settings.gfxData.DrawEllipse(pen, boundingRectangle.X, boundingRectangle.Y, boundingRectangle.Width, boundingRectangle.Height); }
public void Render(PlotDimensions dims, Bitmap bmp, bool lowQuality = false) { using (Graphics gfx = GDI.Graphics(bmp, lowQuality)) using (Pen backgroundPen = GDI.Pen(dataBackgroundColor)) using (Pen outlinePen = GDI.Pen(outlineColor, outlineSize)) using (Brush brush = GDI.Brush(Color.Black)) using (Brush fontBrush = GDI.Brush(centerTextColor)) using (Font sliceFont = GDI.Font(null, sliceFontSize)) using (Font centerFont = GDI.Font(null, centerFontSize)) using (StringFormat sfCenter = new StringFormat() { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center }) { double[] proportions = values.Select(x => x / values.Sum()).ToArray(); AxisLimits2D limits = GetLimits(); double centreX = limits.xCenter; double centreY = limits.yCenter; float diameterPixels = .9f * Math.Min(dims.DataWidth, dims.DataHeight); // record label details and draw them after slices to prevent cover-ups double[] labelXs = new double[values.Length]; double[] labelYs = new double[values.Length]; string[] labelStrings = new string[values.Length]; RectangleF boundingRectangle = new RectangleF( dims.GetPixelX(centreX) - diameterPixels / 2, dims.GetPixelY(centreY) - diameterPixels / 2, diameterPixels, diameterPixels); if (donutSize > 0) { GraphicsPath graphicsPath = new GraphicsPath(); float donutDiameterPixels = (float)donutSize * diameterPixels; RectangleF donutHoleBoundingRectangle = new RectangleF( dims.GetPixelX(centreX) - donutDiameterPixels / 2, dims.GetPixelY(centreY) - donutDiameterPixels / 2, donutDiameterPixels, donutDiameterPixels); graphicsPath.AddEllipse(donutHoleBoundingRectangle); Region excludedRegion = new Region(graphicsPath); gfx.ExcludeClip(excludedRegion); } double start = -90; for (int i = 0; i < values.Length; i++) { // determine where the slice is to be drawn double sweep = proportions[i] * 360; double sweepOffset = explodedChart ? -1 : 0; double angle = (Math.PI / 180) * ((sweep + 2 * start) / 2); double xOffset = explodedChart ? 3 * Math.Cos(angle) : 0; double yOffset = explodedChart ? 3 * Math.Sin(angle) : 0; // record where and what to label the slice double sliceLabelR = 0.35 * diameterPixels; labelXs[i] = (boundingRectangle.X + diameterPixels / 2 + xOffset + Math.Cos(angle) * sliceLabelR); labelYs[i] = (boundingRectangle.Y + diameterPixels / 2 + yOffset + Math.Sin(angle) * sliceLabelR); string sliceLabelValue = (showValues) ? $"{values[i]}" : ""; string sliceLabelPercentage = showPercentages ? $"{proportions[i] * 100:f1}%" : ""; string sliceLabelName = (showLabels && groupNames != null) ? groupNames[i] : ""; labelStrings[i] = $"{sliceLabelValue}\n{sliceLabelPercentage}\n{sliceLabelName}".Trim(); ((SolidBrush)brush).Color = colors[i]; gfx.FillPie(brush: brush, x: (int)(boundingRectangle.X + xOffset), y: (int)(boundingRectangle.Y + yOffset), width: boundingRectangle.Width, height: boundingRectangle.Height, startAngle: (float)start, sweepAngle: (float)(sweep + sweepOffset)); if (explodedChart) { gfx.DrawPie( pen: backgroundPen, x: (int)(boundingRectangle.X + xOffset), y: (int)(boundingRectangle.Y + yOffset), width: boundingRectangle.Width, height: boundingRectangle.Height, startAngle: (float)start, sweepAngle: (float)(sweep + sweepOffset)); } start += sweep; } ((SolidBrush)brush).Color = Color.White; for (int i = 0; i < values.Length; i++) { if (!string.IsNullOrWhiteSpace(labelStrings[i])) { gfx.DrawString(labelStrings[i], sliceFont, brush, (float)labelXs[i], (float)labelYs[i], sfCenter); } } if (outlineSize > 0) { gfx.DrawEllipse( outlinePen, boundingRectangle.X, boundingRectangle.Y, boundingRectangle.Width, boundingRectangle.Height); } gfx.ResetClip(); if (centerText != null) { gfx.DrawString(centerText, centerFont, fontBrush, dims.GetPixelX(0), dims.GetPixelY(0), sfCenter); } if (explodedChart) { // draw a background-colored circle around the perimeter to make it look like all pieces are the same size backgroundPen.Width = 20; gfx.DrawEllipse( pen: backgroundPen, x: boundingRectangle.X, y: boundingRectangle.Y, width: boundingRectangle.Width, height: boundingRectangle.Height); } } }
public override void Render(Settings settings) { double[] proportions = values.Select(x => x / values.Sum()).ToArray(); int sliceOutlineWidth = 0; if (explodedChart) { pen.Color = settings.DataBackground.Color; // TODO: will fail if data background is transparent sliceOutlineWidth = 1; } AxisLimits2D limits = GetLimits(); double centreX = limits.xCenter; double centreY = limits.yCenter; float diameterPixels = .9f * Math.Min(settings.dataSize.Width, settings.dataSize.Height); string fontName = Config.Fonts.GetSansFontName(); float fontSize = 12; // record label details and draw them after slices to prevent cover-ups double[] labelXs = new double[values.Length]; double[] labelYs = new double[values.Length]; string[] labelStrings = new string[values.Length]; RectangleF boundingRectangle = new RectangleF((float)settings.GetPixelX(centreX) - diameterPixels / 2, (float)settings.GetPixelY(centreY) - diameterPixels / 2, diameterPixels, diameterPixels); if (donutSize > 0) { GraphicsPath graphicsPath = new GraphicsPath(); float donutDiameterPixels = (float)donutSize * diameterPixels; RectangleF donutHoleBoundingRectangle = new RectangleF((float)settings.GetPixelX(centreX) - donutDiameterPixels / 2, (float)settings.GetPixelY(centreY) - donutDiameterPixels / 2, donutDiameterPixels, donutDiameterPixels); graphicsPath.AddEllipse(donutHoleBoundingRectangle); Region excludedRegion = new Region(graphicsPath); settings.gfxData.ExcludeClip(excludedRegion); } double start = -90; for (int i = 0; i < values.Length; i++) { // determine where the slice is to be drawn double sweep = proportions[i] * 360; double sweepOffset = explodedChart ? -1 : 0; double angle = (Math.PI / 180) * ((sweep + 2 * start) / 2); double xOffset = explodedChart ? 3 * Math.Cos(angle) : 0; double yOffset = explodedChart ? 3 * Math.Sin(angle) : 0; // record where and what to label the slice double sliceLabelR = 0.35 * diameterPixels; labelXs[i] = (boundingRectangle.X + diameterPixels / 2 + xOffset + Math.Cos(angle) * sliceLabelR); labelYs[i] = (boundingRectangle.Y + diameterPixels / 2 + yOffset + Math.Sin(angle) * sliceLabelR); string sliceLabelValue = (showValues) ? $"{values[i]}" : ""; string sliceLabelPercentage = showPercentages ? $"{proportions[i] * 100:f1}%" : ""; string sliceLabelName = (showLabels) ? groupNames[i] : ""; labelStrings[i] = $"{sliceLabelValue}\n{sliceLabelPercentage}\n{sliceLabelName}".Trim(); brush.Color = colors[i]; settings.gfxData.FillPie(brush: brush, x: (int)(boundingRectangle.X + xOffset), y: (int)(boundingRectangle.Y + yOffset), width: boundingRectangle.Width, height: boundingRectangle.Height, startAngle: (float)start, sweepAngle: (float)(sweep + sweepOffset)); if (explodedChart) { pen.Color = settings.DataBackground.Color; // TODO: will fail if data background is transparent pen.Width = sliceOutlineWidth; settings.gfxData.DrawPie( pen: pen, x: (int)(boundingRectangle.X + xOffset), y: (int)(boundingRectangle.Y + yOffset), width: boundingRectangle.Width, boundingRectangle.Height, startAngle: (float)start, sweepAngle: (float)(sweep + sweepOffset)); } start += sweep; } brush.Color = Color.White; var font = new Font(fontName, fontSize); for (int i = 0; i < values.Length; i++) { if (!string.IsNullOrWhiteSpace(labelStrings[i])) { settings.gfxData.DrawString(labelStrings[i], font, brush, (float)labelXs[i], (float)labelYs[i], settings.misc.sfCenterCenter); } } if (outlineSize > 0) { pen.Width = outlineSize; pen.Color = outlineColor; settings.gfxData.DrawEllipse(pen, boundingRectangle.X, boundingRectangle.Y, boundingRectangle.Width, boundingRectangle.Height); } settings.gfxData.ResetClip(); if (centerText != null) { brush.Color = centerTextColor; Font donutHoleFont = new Font(fontName, centerTextSize); settings.gfxData.DrawString(centerText, donutHoleFont, brush, settings.GetPixel(0, 0), settings.misc.sfCenterCenter); donutHoleFont.Dispose(); } if (explodedChart) { // draw a background-colored circle around the perimeter to make it look like all pieces are the same size pen.Width = 20; settings.gfxData.DrawEllipse( pen: pen, x: boundingRectangle.X, y: boundingRectangle.Y, width: boundingRectangle.Width, height: boundingRectangle.Height); } }
public void SetLimits(AxisLimits2D limits, int xAxisIndex, int yAxisIndex) { XAxes[xAxisIndex].SetLimits(limits.X1, limits.X2); YAxes[yAxisIndex].SetLimits(limits.Y1, limits.Y2); }