Пользовательский элемент управления. Создание клиентского приложения. Развитие серверного проекта, страница 5

}

//=== Заполнение AxisData для любой из осей

public void Scale (ref AxisData data)

{

if (points.Length == 0)

return;

data.max = data.bX ? points[0].X : points[0].Y; // Поиск экстремумов

data.min = data.max;

foreach (PointF p in points)

{

float d = data.bX ? p.X : p.Y;

if (d < data.min)

data.min = d;

else if (d > data.max)

data.max = d;

}

//===== Максимальная амплитуда двух экстремумов

double ext = Math.Max (Math.Abs (data.min), Math.Abs(data.max));

//=== Искусственно увеличиваем порядок экстремума на 3 единицы.

//=== Хотим покрыть 7 порядков, не переходя к экспоненцеальной форме

double power = ext;

if (ext > 0)

power = Math.Log10 (ext) + 3;

data.power = (float)Math.Floor (power / 7);

//===== Если не укладываемся в этот диапазон, восстанавливаем порядок

if (data.power != 0)

data.power = (float)Math.Floor (power) - 3;

data.factor = (float)Math.Pow (10, data.power);// Реальный множитель

//===== Диапазон изменения мантиссы

double span = (data.max - data.min) / data.factor;

if (span == 0)     // Если он нулевой, искусственно раздвигаем график

span = 0.5f;

data.step = CalcStep (span); // Подбираем стандартный шаг мантиссы

data.dStep = data.step * data.factor; // Реальный шаг

//=== Начальная линия сетки д.б. кратна шагу и быть меньше минимума

data.dStart = data.dStep * (float)Math.Floor (data.min / data.dStep);

data.start = data.dStart / data.factor; // Начальная линия сетки (мантисса)

for (data.end = data.start; // Вычисляем последнюю линию сетки

data.end < data.min / data.factor + span - 1e-15;

data.end += data.step)

;

data.dEnd = data.end * data.factor;

float length = data.bX ? (rb.X - lt.X) : (rb.Y - lt.Y);

data.scale = length / (data.factor * (data.end - data.start));

}

float ToPixelX (float x) // Переход к пиксельным координатам

{

return lt.X + (x - dataX.dStart) * dataX.scale;

}

float ToPixelY (float y)

{

return rb.Y - (y - dataY.dStart) * dataY.scale;

}

public void Draw (Graphics g) // Изображение графика в заданном контексте

{

GraphicsPath path = new GraphicsPath ();

path.AddArc (0, 0, 40, 40, 180, 90);

path.AddLine (20, 0, size.Width-20, 0);

path.AddArc (size.Width-40, 0, 40, 40, 270, 90);

path.AddLine (size.Width, 20, size.Width, size.Height-20);

path.AddArc (size.Width-40, size.Height-40, 40, 40, 0, 90);

path.AddLine (size.Width-20, size.Height, 20, size.Height);

path.AddArc (0, size.Height-40, 40, 40, 90, 90);

path.CloseFigure();

g.FillPath (Brushes.AliceBlue, path);

g.DrawPath (new Pen (Color.DarkBlue, 0), path);

SolidBrush brush = new SolidBrush(Color.FromArgb(255,255,250));

g.FillRectangle (brush, lt.X, lt.Y, rb.X-lt.X, rb.Y-lt.Y);

Scale (ref dataX);

Scale (ref dataY);

string s = String.Format (  // Выводим экстремумы функции

"Min = {0:g4}      Max = {1:g4}", dataY.min, dataY.max);

Font font = new Font("Tahoma", 10, FontStyle.Bold);

SizeF sz = g.MeasureString (s, font);

int

w = (int)sz.Width/2 + 8,

ww = w + w,

wm = w - 8;

g.FillRectangle (Brushes.DarkGray, bc.X-w, bc.Y+2, ww, hh);

brush = new SolidBrush (Color.FromArgb(200,220,255));

g.FillRectangle (brush, bc.X-w-4, bc.Y-2, ww, hh);

g.DrawString (s, font, Brushes.Black, bc.X-wm, bc.Y+3);

//====== Готовимся изображать координатную сетку

StringFormat fmt = new StringFormat();

fmt.Alignment = StringAlignment.Center;

//====== Вывод меток осей

g.DrawString (title, new Font("Arial", 14), Brushes.DarkBlue,

bc.X-10, lt.Y-hh, fmt);

g.DrawString (sX, wnd.Font, Brushes.Black, rb.X-h, rb.Y+h2);

Pen pen = new Pen (Color.Black, 0);

Pen gridPen = new Pen (Color.DarkGray, 0);

//====== Вертикальные линии сетки

for (float x = dataX.start; x < dataX.end-dataX.step/2; x += dataX.step)

{

float xi = ToPixelX (x * dataX.factor);

g.DrawLine (gridPen, xi, lt.Y, xi, rb.Y);

s = MakeLabel (true, x);

g.DrawString (s, wnd.Font, Brushes.Black, xi, rb.Y+h2, fmt);

}

//=== Повторяем цикл для горизонтальных линий сетки

for (float y = dataY.start; y < dataY.end-dataY.step/2; y += dataY.step)