Основная проблема заключается в том, что график, с которым я работаю, не является стандартным элементом управления Visual Studio, а является пользовательским. Не все функции были разработаны и документация не была предоставлена. Прямо сейчас я вроде понимаю, как это работает, но я думаю, что я застрял здесь с математической задачей.
Описание: У нас есть график с n кривыми, где 0 . Каждая кривая имеет свой масштаб, поэтому значения осей X и Y меняются. Пример кривых, которые обычно отображаются на графике
Ввод: TotalYLength, TotalValue, DivisionValue .
Где: TotalYLength - это разница между нижней и верхней сторонами отображаемой области (я полагаю).
TotalValue - длина оси Y текущей кривой.
DivisionValue - шаг сетки (значение по умолчанию жестко задано как 200, но может быть изменено).
Существует также StartValue , которая является первой точкой Y кривой, но она не использовалась в приведенной ниже формуле.
Существующее решение:
float newDivitionPixels = (float) ((totalYLength * _divisionValue) / TotalValue);
Например: 343 * 200/1000 = 68,6
После одного уменьшения: 343 * 200/2000 = 34,3
После двух уменьшений: 343 * 200/4000 = 17,15
Масштабирование график вместе со значениями сетки: чем больше мы уменьшаем масштаб - тем больше сеток мы получаем на экране.
Выпуск: Количество масштабирования s out неограничен, и это нормально, но сетки продолжают добавляться, делая этот нечитабельный вывод и останавливая приложение, когда их слишком много.
нечитаемые значения после нескольких уменьшений
Задача: Найдите формулу, которая будет корректировать масштабирование для каждой конкретной кривой с ограниченным увеличением линий сетки слева или без изменения их числа вообще.
Я пытался присвоить число 45 переменной newDivitionPixels (я нашел это число экспериментально. Выдает ровно одиннадцать значений сетки). А также логарифмы, такие как:
TotalYLength * Math.Log(TotalYLength);
(TotalYLength * Math.Log(TotalYLength)) / TotalValue;
Math.Log(45, TotalYLength);
(totalYLength / Math.Log(TotalValue));
и так далее. Последний даже решил проблему с сетками, но вывел неверные значения масштабирования. Я считаю, что мне просто нужна точная математическая формула, которая будет отображать как правильные значения, так и ограниченное количество сеток. Но я предполагаю, что могло бы быть решение алгоритми c я не вижу. Буду благодарен за любые рабочие предложения, так как я уже потратил недели на то, чтобы найти и поэкспериментировать с этой частью. Вот код метода, который задает aws линии сетки.
public void DrawAxis(Graphics graphics, Rectangle rectangle)
{
PointF pt1 = new PointF(XGap, YGap1);
PointF pt2 = new PointF(XGap, rectangle.Height - YGap1);
graphics.DrawLine(Pen, pt1, pt2); //Draws a vertical line across the Y-axis grids
log.Debug("Draw a line from pt1 {0} to pt2 {1}", pt1.Y.ToString(), pt2.Y);
float totalYLength = pt2.Y - pt1.Y;
if (totalYLength < 0)
{
totalYLength = totalYLength * -1;
}
float newDivitionPixels = (float) ((totalYLength * _divisionValue) / TotalValue);
_divisionDst = newDivitionPixels;
if (_selected)
{
PointF ptOrigin = pt2;
float ptFirstDivY = pt2.Y - ((float)((newDivitionPixels * (StartValue - Origin)) / _divisionValue));
PointF ptFisrtDiv = ptOrigin;
ptFisrtDiv.Y = ptFirstDivY;
// Draw first division
PointF ptFisrtDiv1 = ptFisrtDiv;
ptFisrtDiv1.X = ptFisrtDiv1.X - 6;
graphics.DrawLine(Pen, ptFisrtDiv1, ptFisrtDiv);
log.Debug("Draw a line from ptFisrtDiv1 {0} to ptFisrtDiv {1}", ptFisrtDiv1, ptFisrtDiv);
// Draw grid lines
float[] dashValues = { 3, 1 };
Pen grayPen = new Pen(Color.Gray, 1);
grayPen.DashPattern = dashValues;
int tempX = (int)(ptFisrtDiv.X + _graphControl.UIControl.Width - _graphControl.XAxis.XGap1 - 20);
PointF ptTop = new PointF(tempX, ptFisrtDiv.Y);
graphics.DrawLine(grayPen, ptFisrtDiv, ptTop); //Draws longer lines for the enumerated grids
log.Debug("Draw a line from ptFisrtDiv {0} to ptTop {1}", ptFisrtDiv, ptTop);
//
{
// Draws divisions in -ve side
PointF divPt1 = ptFisrtDiv1;
PointF divPt2 = ptFisrtDiv;
divPt1.X = divPt1.X + 4;
for (int i = 1; i <= 4; i++)
{
divPt1.Y = divPt1.Y + newDivitionPixels / 5;
divPt2.Y = divPt2.Y + newDivitionPixels / 5;
if (divPt2.Y > ptOrigin.Y)
{
break;
}
graphics.DrawLine(Pen, divPt2, divPt1); //Draws four shorter lines for the grids between two numbers
log.Debug("Draw a line from divPt2 {0} to divPt1 {1}", divPt2, divPt1);
}
// Draws divisions in +ve side
PointF tpPt1 = ptFisrtDiv1;
tpPt1.X = tpPt1.X + 4;
PointF tpPt2 = ptFisrtDiv;
for (int i = 1; i <= 4; i++)
{
tpPt1.Y = tpPt1.Y - newDivitionPixels / 5;
tpPt2.Y = tpPt2.Y - newDivitionPixels / 5;
if (tpPt1.Y < pt1.Y)
{
break;
}
graphics.DrawLine(Pen, tpPt1, tpPt2);
log.Debug("Draw a line from tpPt1 {0} to tpPt2 {1}", tpPt1, tpPt2);
}
PointF ptToDrawStr = ptFisrtDiv1;
ptToDrawStr.X = ptToDrawStr.X - 40;
string strToDraw = StartValue.ToString();
strToDraw = GetTrimmedStr(strToDraw);
graphics.DrawString(strToDraw, _graphControl.UIControl.Font, Pen.Brush, ptToDrawStr);
log.Debug("Draw a string {0} at ptToDrawStr.Y {1}", strToDraw, ptToDrawStr);
}
{
PointF divPt1 = ptFisrtDiv1;
PointF divPt2 = ptFisrtDiv;
double yAxisDivisionValue = StartValue;
while (true)
{
divPt2.Y = divPt2.Y - newDivitionPixels;
divPt1.Y = divPt1.Y - newDivitionPixels;
if (divPt1.Y < pt1.Y)
{
break;
}
yAxisDivisionValue = yAxisDivisionValue + _divisionValue;
graphics.DrawLine(Pen, divPt2, divPt1);
log.Debug("Draw a line from divPt2 {0} to divPt1 {1}", divPt2, divPt1);
// Draw grid lines
tempX = (int)(divPt2.X + _graphControl.UIControl.Width - _graphControl.XAxis.XGap1 - 20);
ptTop = new PointF(tempX, divPt2.Y);
graphics.DrawLine(grayPen, divPt2, ptTop);
log.Debug("Draw a line from divPt2 {0} to ptTop {1}", divPt2, ptTop);
// Draw small divisions
PointF tpPt1 = divPt1;
tpPt1.X = tpPt1.X + 4;
PointF tpPt2 = divPt2;
for (int i = 1; i <= 4; i++)
{
tpPt1.Y = tpPt1.Y - newDivitionPixels / 5;
tpPt2.Y = tpPt2.Y - newDivitionPixels / 5;
if (tpPt1.Y < pt1.Y)
{
break;
}
graphics.DrawLine(Pen, tpPt1, tpPt2);
log.Debug("Draw a line from tpPt1 {0} to tpPt2 {1}", tpPt1, tpPt2);
}
PointF ptToDrawStr = divPt1;
ptToDrawStr.X = ptToDrawStr.X - 40;
string strTemp = yAxisDivisionValue.ToString();
strTemp = GetTrimmedStr(strTemp);
graphics.DrawString(strTemp, _graphControl.UIControl.Font, Pen.Brush, ptToDrawStr);
log.Debug("Draw a string {0} at ptToDrawStr {1}", strTemp, ptToDrawStr);
}
}
PointF ptDesc = new PointF();
ptDesc.X = 20;
ptDesc.Y = _graphControl.UIControl.Height / 3;
System.Drawing.StringFormat drawFormat = new System.Drawing.StringFormat();
drawFormat.FormatFlags = StringFormatFlags.DirectionVertical | StringFormatFlags.DirectionRightToLeft | StringFormatFlags.NoWrap;
graphics.DrawString(AxisDescription, _graphControl.UIControl.Font, Pen.Brush, ptDesc, drawFormat);
}
}
PS На оси X этой проблемы нет, но ее формула не соответствует этому методу.