/// <summary> /// Gets the width of a unit in the chart /// </summary> /// <param name="source">axis orientation</param> /// <param name="chart">chart model to get the scale at</param> /// <param name="axis">axis instance</param> /// <returns></returns> public static double GetUnitWidth(AxisOrientation source, ChartCore chart, AxisCore axis) { double min; double u; if (source == AxisOrientation.Y) { min = axis.BotLimit; u = axis.View.BarUnit; return(ToDrawMargin(min, AxisOrientation.Y, chart, axis) - ToDrawMargin(min + u, AxisOrientation.Y, chart, axis)); } min = axis.BotLimit; u = axis.View.BarUnit; return(ToDrawMargin(min + u, AxisOrientation.X, chart, axis) - ToDrawMargin(min, AxisOrientation.X, chart, axis)); }
/// <summary> /// Converts from chart values to chart control size. /// </summary> /// <param name="value">value to scale</param> /// <param name="source">axis orientation to scale value at</param> /// <param name="chart">chart model to scale value at</param> /// <param name="axis">axis model instance</param> /// <returns></returns> public static double ToPlotArea(double value, AxisOrientation source, ChartCore chart, AxisCore axis) { var p1 = new CorePoint(); var p2 = new CorePoint(); if (source == AxisOrientation.Y) { p1.X = axis.TopLimit; p1.Y = chart.DrawMargin.Top; p2.X = axis.BotLimit; p2.Y = chart.DrawMargin.Top + chart.DrawMargin.Height; } else { p1.X = axis.TopLimit; p1.Y = chart.DrawMargin.Width + chart.DrawMargin.Left; p2.X = axis.BotLimit; p2.Y = chart.DrawMargin.Left; } var deltaX = p2.X - p1.X; // ReSharper disable once CompareOfFloatsByEqualityOperator var m = (p2.Y - p1.Y) / (deltaX == 0 ? double.MinValue : deltaX); return(m * (value - p1.X) + p1.Y); }
/// <summary> /// Converts from chart values to chart draw margin size. /// </summary> /// <param name="value">value to scale</param> /// <param name="source">axis orientation</param> /// <param name="chart">chart model to scale the value at</param> /// <param name="axis">axis instance to scale the value at</param> /// <returns></returns> public static double ToDrawMargin(double value, AxisOrientation source, ChartCore chart, AxisCore axis) { var o = source == AxisOrientation.X ? chart.DrawMargin.Left : chart.DrawMargin.Top; return(ToPlotArea(value, source, chart, axis) - o); }
public LabelEvaluation(double angle, double w, double h, AxisCore axis, AxisTags source) { const double padding = 4; ActualWidth = w; ActualHeight = h; // for now there is no support for rotated and merged labels. // the labels will be rotated but there is no warranty that they are displayed correctly if (axis.View.IsMerged) { Top = 0; Bottom = 0; Left = 0; Right = 0; if (source == AxisTags.Y) { XOffset = padding; YOffset = padding; } else { if (axis.Position == AxisPosition.LeftBottom) { //Bot XOffset = padding; YOffset = -h*2 - padding; } else { //Top XOffset = padding; YOffset = padding + h*2; } } return; } //OK now lets evaluate the rotation angle... // the rotation angle starts from an horizontal line, yes like this text // - 0°, | 90°, - 180°, | 270° // notice normally rotating a label from 90 to 270° will show the label // in a wrong orientation // we need to fix that angle const double toRadians = Math.PI/180; // 1. width components // 2. height components WFromW = Math.Abs(Math.Cos(angle*toRadians)*w); // W generated from the width of the label WFromH = Math.Abs(Math.Sin(angle*toRadians)*h); // W generated from the height of the label HFromW = Math.Abs(Math.Sin(angle*toRadians)*w); // H generated from the width of the label HFromH = Math.Abs(Math.Cos(angle*toRadians)*h); // H generated from the height of the label LabelAngle = angle%360; if (LabelAngle < 0) LabelAngle += 360; if (LabelAngle > 90 && LabelAngle < 270) LabelAngle = (LabelAngle + 180)%360; //at this points angles should only exist in 1st and 4th quadrant //those are the only quadrants that generates readable labels //the other 2 quadrants display inverted labels var quadrant = ((int) (LabelAngle/90))%4 + 1; if (source == AxisTags.Y) { // Y Axis if (quadrant == 1) { if (axis.Position == AxisPosition.LeftBottom) { // 1, L Top = HFromW + (HFromH/2); //space taken from separator to top Bottom = TakenHeight - Top; //space taken from separator to bottom XOffset = -WFromW - padding; //distance from separator to label origin in X YOffset = -Top; //distance from separator to label origin in Y } else { // 1, R Bottom = HFromW + (HFromH/2); Top = TakenHeight - Bottom; XOffset = padding + WFromH; YOffset = -Top; } } else { if (axis.Position == AxisPosition.LeftBottom) { // 4, L Bottom = HFromW + (HFromH/2); Top = TakenHeight - Bottom; XOffset = -TakenWidth - padding; YOffset = HFromW - (HFromH/2); } else { // 4, R Top = HFromW + (HFromH/2); Bottom = TakenHeight - Top; XOffset = padding; YOffset = -Bottom; } } } else { // X Axis //axis x has one exception, if labels rotation equals 0° then the label is centered if (Math.Abs(axis.View.LabelsRotation) < .01) { Left = TakenWidth / 2; Right = Left; XOffset = -Left; YOffset = axis.Position == AxisPosition.LeftBottom ? padding : -padding - TakenHeight; } else { if (quadrant == 1) { if (axis.Position == AxisPosition.LeftBottom) { //1, B Right = WFromW + (WFromH / 2); //space taken from separator to right Left = TakenWidth - Right; //space taken from separator to left XOffset = Left; //distance from separator to label origin in X YOffset = padding; //distance from separator to label origin in Y } else { //1, T Left = WFromW + (WFromH/2); Right = TakenWidth - Left; XOffset = -WFromW; YOffset = -padding - TakenHeight; } } else { if (axis.Position == AxisPosition.LeftBottom) { //4, B Left = WFromW + (WFromH/2); Right = TakenWidth - Left; XOffset = -Left; YOffset = padding + HFromW; } else { //4, T Right = WFromW + (WFromH/2); Left = TakenWidth - Right; XOffset = -Left; YOffset = -HFromH; } } } } }
public LabelEvaluation(double angle, double w, double h, AxisCore axis, AxisTags source) { const double padding = 4; ActualWidth = w; ActualHeight = h; // for now there is no support for rotated and merged labels. // the labels will be rotated but there is no warranty that they are displayed correctly if (axis.View.IsMerged) { Top = 0; Bottom = 0; Left = 0; Right = 0; if (source == AxisTags.Y) { XOffset = padding; YOffset = padding; } else { if (axis.Position == AxisPosition.LeftBottom) { //Bot XOffset = padding; YOffset = -h * 2 - padding; } else { //Top XOffset = padding; YOffset = padding + h * 2; } } return; } //OK now lets evaluate the rotation angle... // the rotation angle starts from an horizontal line, yes like this text // - 0°, | 90°, - 180°, | 270° // notice normally rotating a label from 90 to 270° will show the label // in a wrong orientation // we need to fix that angle const double toRadians = Math.PI / 180; // 1. width components // 2. height components WFromW = Math.Abs(Math.Cos(angle * toRadians) * w); // W generated from the width of the label WFromH = Math.Abs(Math.Sin(angle * toRadians) * h); // W generated from the height of the label HFromW = Math.Abs(Math.Sin(angle * toRadians) * w); // H generated from the width of the label HFromH = Math.Abs(Math.Cos(angle * toRadians) * h); // H generated from the height of the label LabelAngle = angle % 360; if (LabelAngle < 0) { LabelAngle += 360; } if (LabelAngle > 90 && LabelAngle < 270) { LabelAngle = (LabelAngle + 180) % 360; } //at this points angles should only exist in 1st and 4th quadrant //those are the only quadrants that generates readable labels //the other 2 quadrants display inverted labels var quadrant = ((int)(LabelAngle / 90)) % 4 + 1; if (source == AxisTags.Y) { // Y Axis if (quadrant == 1) { if (axis.Position == AxisPosition.LeftBottom) { // 1, L Top = HFromW + (HFromH / 2); //space taken from separator to top Bottom = TakenHeight - Top; //space taken from separator to bottom XOffset = -WFromW - padding; //distance from separator to label origin in X YOffset = -Top; //distance from separator to label origin in Y } else { // 1, R Bottom = HFromW + (HFromH / 2); Top = TakenHeight - Bottom; XOffset = padding + WFromH; YOffset = -Top; } } else { if (axis.Position == AxisPosition.LeftBottom) { // 4, L Bottom = HFromW + (HFromH / 2); Top = TakenHeight - Bottom; XOffset = -TakenWidth - padding; YOffset = HFromW - (HFromH / 2); } else { // 4, R Top = HFromW + (HFromH / 2); Bottom = TakenHeight - Top; XOffset = padding; YOffset = -Bottom; } } } else { // X Axis //axis x has one exception, if labels rotation equals 0° then the label is centered if (Math.Abs(axis.View.LabelsRotation) < .01) { Left = TakenWidth / 2; Right = Left; XOffset = -Left; YOffset = axis.Position == AxisPosition.LeftBottom ? padding : -padding - TakenHeight; } else { if (quadrant == 1) { if (axis.Position == AxisPosition.LeftBottom) { //1, B Right = WFromW + (WFromH / 2); //space taken from separator to right Left = TakenWidth - Right; //space taken from separator to left XOffset = Left; //distance from separator to label origin in X YOffset = padding; //distance from separator to label origin in Y } else { //1, T Left = WFromW + (WFromH / 2); Right = TakenWidth - Left; XOffset = -WFromW; YOffset = -padding - TakenHeight; } } else { if (axis.Position == AxisPosition.LeftBottom) { //4, B Left = WFromW + (WFromH / 2); Right = TakenWidth - Left; XOffset = -Left; YOffset = padding + HFromW; } else { //4, T Right = WFromW + (WFromH / 2); Left = TakenWidth - Right; XOffset = -Left; YOffset = -HFromH; } } } } }
/// <summary> /// Converts from chart values to chart control size. /// </summary> /// <param name="value">value to scale</param> /// <param name="source">axis orientation to scale value at</param> /// <param name="chart">chart model to scale value at</param> /// <param name="axis">axis model instance</param> /// <returns></returns> public static double ToPlotArea(double value, AxisOrientation source, ChartCore chart, AxisCore axis) { var p1 = new CorePoint(); var p2 = new CorePoint(); if (source == AxisOrientation.Y) { p1.X = axis.TopLimit; p1.Y = chart.DrawMargin.Top; p2.X = axis.BotLimit; p2.Y = chart.DrawMargin.Top + chart.DrawMargin.Height; } else { p1.X = axis.TopLimit; p1.Y = chart.DrawMargin.Width + chart.DrawMargin.Left; p2.X = axis.BotLimit; p2.Y = chart.DrawMargin.Left; } var deltaX = p2.X - p1.X; // ReSharper disable once CompareOfFloatsByEqualityOperator var m = (p2.Y - p1.Y) / (deltaX == 0 ? double.MinValue : deltaX); return m * (value - p1.X) + p1.Y; }
/// <summary> /// Converts from chart values to chart draw margin size. /// </summary> /// <param name="value">value to scale</param> /// <param name="source">axis orientation</param> /// <param name="chart">chart model to scale the value at</param> /// <param name="axis">axis instance to scale the value at</param> /// <returns></returns> public static double ToDrawMargin(double value, AxisOrientation source, ChartCore chart, AxisCore axis) { var o = source == AxisOrientation.X ? chart.DrawMargin.Left : chart.DrawMargin.Top; return ToPlotArea(value, source, chart, axis) - o; }
/// <summary> /// Gets the width of a unit in the chart /// </summary> /// <param name="source">axis orientation</param> /// <param name="chart">chart model to get the scale at</param> /// <param name="axis">axis instance</param> /// <returns></returns> public static double GetUnitWidth(AxisOrientation source, ChartCore chart, AxisCore axis) { double min; double u; if (source == AxisOrientation.Y) { min = axis.BotLimit; u = axis.View.BarUnit; return ToDrawMargin(min, AxisOrientation.Y, chart, axis) - ToDrawMargin(min + u, AxisOrientation.Y, chart, axis); } min = axis.BotLimit; u = axis.View.BarUnit; return ToDrawMargin(min + u, AxisOrientation.X, chart, axis) - ToDrawMargin(min, AxisOrientation.X, chart, axis); }