О рисовании простейших диаграмм в приложениях Windows
Аннотация: Данная статья написана после очередного вопроса или даже просьбы - прислать исходный
код, для того, чтобы рисовать простейшие диаграммы, как это сделано в популярной программе
"LitFrequencyMeter - программа определения частоты повторения слов и
знаков в текстах, литературных произведениях, статьях и документах". Устав отвечать на вопросы и посылать куски кода
(первое правило программиста - "Вы можете поделиться частью кода программы, но никогда не кодом всей программы -
иначе все будут знать какой вы плохой программист"), а без шуток, когда минимум 3-5 писем в месяц с подобными пожеланиями,
то невольно приходишь к мысли, чем писать лишних пять писем в месяц, лучше поместить кусок кода на сайте - умный разберется что к чему,
а кому не дано, хоть спрашивать не будет из-за того, что не смог разобраться.
Поэтому на сайте приведен класс из программы "LitFrequencyMeter", позволяющий рисовать простейшие диаграммы: линейную, гистограмму и круговую.
Тот минимум комментариев, который присутствует в тексте кода, по мнению автора достаточен для самостоятельной работы по включению класса
в свой код программы.
В начало
Параграф 1. Класс рисования простейших диаграмм
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace SearcherPhrases
{
class PaitCl
{
//Специально подобранные заливки и цвета
private Brush[] br ={Brushes.LightGreen,Brushes.Chartreuse,Brushes.LimeGreen,Brushes.Green,Brushes.DarkGreen,
Brushes.DarkOliveGreen,Brushes.LightPink,Brushes.LightSeaGreen,Brushes.LightCoral,Brushes.DarkCyan ,
Brushes.Crimson,Brushes.CornflowerBlue ,Brushes.Chocolate,Brushes.CadetBlue,Brushes.BlueViolet,
Brushes.Maroon, Brushes.Blue,Brushes.Brown,Brushes.DarkBlue, Brushes.Red,
Brushes.Coral,Brushes.DarkRed, Brushes.DarkMagenta, Brushes.DarkOrange,Brushes.DarkOrchid};
private Color[] color ={Color.LightGreen,Color.Chartreuse,Color.LimeGreen,Color.Green,Color.DarkGreen,
Color.DarkOliveGreen,Color.LightPink ,Color.LightSeaGreen,Color.LightCoral ,Color.DarkCyan ,
Color.Crimson , Color.CornflowerBlue ,Color.Chocolate,Color.CadetBlue,Color.BlueViolet,
Color.Maroon,Color.Blue,Color.Brown,Color.DarkBlue, Color.Red,
Color.Coral,Color.DarkRed, Color.DarkMagenta, Color.DarkOrange,Color.DarkOrchid};
//Будущий рисунок
private Bitmap bmp = null;
private Graphics graph = null;
//Размер рисунка
private int viX = 0;
private int viY = 0;
private float vfXcirc = 0;
private float vfYcirc = 0;
private float viDiamX = 0;
private float viDiamY = 0;
//Разиер массива отображаемых значений
private int viMaxRg = 0;
//Массив значений для отображения
private string[,] rgsZn = null;
//Шрифт по умолчанию
private Font objFont = new Font("Arial", 8, FontStyle.Bold);
private Brush objBrush = null;
//Карандаш
private Pen objPenLine = null;
//Отступы осей от краев холста
private int viDeltaaxisL = 0;
private int viDeltaaxisR = 0;
private int viDeltaaxisH = 0;
private Color colorFont = Color.Black;
#region Конструкторы
//Первый
public PaitCl(int a, int b)
{
bmp = new Bitmap(a, b);
graph = Graphics.FromImage(bmp);
viX = a;
viY = b;
//Карандаш по умолчанию
objPenLine = new Pen(Color.Black, 1);
//Кисть по умолчанию
objBrush = Brushes.Black;
}
//Второй
public PaitCl()
{
//Карандаш по умолчанию
objPenLine = new Pen(Color.Black, 1);
//Кисть по умолчанию
objBrush = Brushes.Black;
}
#endregion
#region Создание картинки при использовании второго конструктора
public void NewBitmap(int a, int b)
{
bmp = new Bitmap(a, b);
graph = Graphics.FromImage(bmp);
viX = a;
viY = b;
}
#endregion
#region Установка цвет фона диаграммы
public void vSetBackground(Color bcl)
{
graph.Clear(bcl);
}
#endregion
#region Карандаш, шрифт, кисть
//Цвет карандаша
public void vSetPenColorLine(Color pcl)
{
if (objPenLine == null)
{
objPenLine = new Pen(Color.Black, 1);
}
objPenLine.Color = pcl;
}
//Установка толщина карандаша
public void vSetPenWidthLine(int penwidth)
{
if (objPenLine == null)
{
objPenLine = new Pen(Color.Black, 1);
}
objPenLine.Width = penwidth;
}
//Установка шрифта
public void vSetFont(string name, float size, bool bold)
{
if (objFont != null) objFont = null;
if (bold)
{
objFont = new Font(name, size, FontStyle.Bold);
}
else
{
objFont = new Font(name, size);
}
}
public void vSetObjFont(Font fnt)
{
objFont=fnt;
}
//Цвет шрифта
public void vSetFontColor(Color color)
{
colorFont = color;
}
//Принудительная кисть
public void vSetBrush(Brush brush)
{
objBrush = brush;
}
#endregion
#region Создание массива
public void vCreateRg(int a)
{
viMaxRg = a;
rgsZn = new string[a, 2];
}
#endregion
#region Перенос массива строк в класс
public void vWriteRg(int a, string s1, string s2)
{
rgsZn[a, 0] = s1;
rgsZn[a, 1] = s2;
}
#endregion
#region Доступ к переменным класса
public Bitmap bmpGet()
{
return bmp;
}
public int iGetX()
{
return viX;
}
public int iGetY()
{
return viY;
}
#endregion
#region Использование картинки для рисования на ней
public void vSet(Bitmap bmpSet)
{
if (bmp == null)
{
bmp = new Bitmap(bmpSet.Width, bmpSet.Height);
}
bmp = bmpSet;
graph = Graphics.FromImage(bmp);
}
#endregion
#region Рисование линии
public void vDravLine(int a, int b, int c, int d)
{
graph.DrawLine(objPenLine, a, b, c, d);
}
#endregion
#region Рисование Осей
public void vDravAxis(int deltaaxisL, int deltaaxisR, int deltaaxisH, Color colorpenaxis, int widthpen)
{
//Запоминаем отступы
viDeltaaxisL = deltaaxisL;
viDeltaaxisR = deltaaxisR;
viDeltaaxisH = deltaaxisH;
//Запоминаем цвет осей и толщину
vSetPenColorLine(colorpenaxis);
if (widthpen > 0) vSetPenWidthLine(widthpen);
//Точка начала рисования по х и y
int x = deltaaxisL;
int y = viY - deltaaxisH;
int x1 = viX - deltaaxisR;
int y1 = deltaaxisH;
int d = widthpen * 10;
//Оси на d пикселей длинней для стрелок
graph.DrawLine(objPenLine, x, y, x1 + d, y);
graph.DrawLine(objPenLine, x, y, x, y1 - d);
int a = 10 * (int)objPenLine.Width;
int b = 2 * (int)objPenLine.Width;
int x2 = x1 - a;
int y2 = y + b;
//Стрелки
graph.DrawLine(objPenLine, x1 + 20, y, x2 + d, y2);
y2 = y - b;
graph.DrawLine(objPenLine, x1 + 20, y, x2 + d, y2);
x2 = x - b;
y2 = y1 + a;
graph.DrawLine(objPenLine, x, y1 - d, x2, y2 - d);
x2 = x + b;
graph.DrawLine(objPenLine, x, y1 - d, x2, y2 - d);
}
#endregion
#region Рисование сетки
public void vDravGrid()
{
float x = viDeltaaxisL;// -objPenLine.Width;
float y = viY - viDeltaaxisH;// +objPenLine.Width;
float x1 = viX - viDeltaaxisR;// +objPenLine.Width;
float y1 = viDeltaaxisH;// -objPenLine.Width;
float f = (y - y1) / (float)viMaxRg;
for (int i = 1; i < viMaxRg + 1; i++)
{
graph.DrawLine(objPenLine, x, y - f * i, x1, y - f * i);
}
f = (x - x1) / (float)(viMaxRg-1);
for (int i = 1; i < viMaxRg; i++)
{
graph.DrawLine(objPenLine, x - f * i, y, x-f*i, y1);
}
}
#endregion
#region Рисование линий графика для линейного графика
public void vDrawGraphLines()
{
string s = string.Empty;
string s1 = string.Empty;
string s2 = string.Empty;
float f = 0;
float f1 = 0;
float x1 = 0;
float x = viDeltaaxisL;//-objPenLine.Width;
float y = viY - viDeltaaxisH;// +objPenLine.Width;
float x2 = 0;
float fMax = float.MinValue;
//float fMin = int.MaxValue;
for (int i = 0; i < viMaxRg; i++)
{
s = rgsZn[i, 0];
if (string.IsNullOrEmpty(s)) break;
if (fMax < float.Parse(s)) fMax = float.Parse(s);
}
//Пикселей для рисования по оси х
float fdeltax = viX - viDeltaaxisL - viDeltaaxisR;
//Пикселей на один отсчет
fdeltax = fdeltax / (float)(viMaxRg - 1);
//Пикселей для рисования по оси y
float fdeltay = viY - 2 * viDeltaaxisH;
//Пикселей на одну единицу массива значений
fdeltay = fdeltay / fMax;
for (int i = 0; i < viMaxRg; i++)
{
//Первый раз запоминаем точку старта
if (i == 0)
{
s = rgsZn[i, 0];
s2 = rgsZn[i, 1];
f = y - (float.Parse(s) * fdeltay);
x1 = x;
}
else
{
s1 = rgsZn[i, 0];
if (string.IsNullOrEmpty(s1)) break;
f1 = y - (float.Parse(s1) * fdeltay);
x2 = x + (int)(fdeltax * i);
graph.DrawLine(objPenLine, x1, f, x2, f1);
s = rgsZn[i, 0];
s2 = rgsZn[i, 1];
f = f1;
x1 = x + (int)(i * fdeltax);
}
}
}
#endregion
#region Рисование графика для гистограммы
public void vDrawGraphRectangular(int a,int c)
{
string s = string.Empty;
string s1 = string.Empty;
string s2 = string.Empty;
float f = 0;
float x1 = 0;
float x = viDeltaaxisL;
float y = viY - viDeltaaxisH;
float fMax = float.MinValue;
for (int i = 0; i < viMaxRg; i++)
{
s = rgsZn[i, 0];
if (fMax < float.Parse(s)) fMax = float.Parse(s);
}
//Пикселей для рисования по оси х
float fdeltax = viX - viDeltaaxisL - viDeltaaxisR;
//Пикселей на один отсчет
fdeltax = fdeltax / (float)(viMaxRg - 1);
//Пикселей для рисования по оси y
float fdeltay = viY - 2 * viDeltaaxisH;
//Пикселей на одну единицу массива значений
fdeltay = fdeltay / fMax;
float fdx=0;
if (c != 0) fdx = (fdeltax * c / 100)/2;
Random rand = new Random(DateTime.Now.Millisecond);
int arn = rand.Next((int)br.Length);
objBrush = br[arn];
for (int i = 0; i < viMaxRg - 1; i++)
{
s = rgsZn[i, 0];
f = float.Parse(s);
x1 = x + ((float)i * fdeltax);
if (a == 0)
{
graph.FillRectangle(objBrush, x1 + fdx, y - fdeltay * f, fdeltax - 2 * fdx, fdeltay * f);
}
else
{
int b = i % br.Length;
graph.FillRectangle(br[b], x1 + fdx, y - fdeltay * f, fdeltax - 2 * fdx, fdeltay * f);
}
if (i == viMaxRg - 2)
{
int b=(i+1) % br.Length;
s = rgsZn[i+1, 0];
f = float.Parse(s);
x1 = x + ((float)(i+1) * fdeltax);
if (a == 0)
{
graph.FillRectangle(objBrush, x1-2, y - fdeltay * f, 4/*fdeltax*/, fdeltay * f);
}
else
{
graph.FillRectangle(br[b], x1-2, y - fdeltay * f, 4/*fdeltax*/, fdeltay * f);
}
}
}
}
#endregion
#region Текст по оси X - цифры 1-размер массива
public void vDrawTextAxXNumber(bool f)
{
//Пикселей для надписей по оси х
float fdeltax = viX - viDeltaaxisL - viDeltaaxisR;
//Пикселей на один отсчет
fdeltax = fdeltax / (float)(viMaxRg - 1);
float x = viDeltaaxisL;
float y = viY - viDeltaaxisH + objPenLine.Width;
for (int i = 1; i < viMaxRg + 1; i++)
{
if (!f || i % 2 == 0)
{
graph.DrawString(Convert.ToString(i), objFont, objBrush, x + (i - 1) * fdeltax, y);
}
else
{
graph.DrawString(Convert.ToString(i), objFont, objBrush, x + (i - 1) * fdeltax, y + objFont.Size);
}
}
}
#endregion
#region Текст по оси X - Значения
public void vDrawTextAxXValues(bool f)
{
string s = string.Empty;
//Пикселей для надписей по оси х
float fdeltax = viX - viDeltaaxisL - viDeltaaxisR;
//Пикселей на один отсчет
fdeltax = fdeltax / (float)(viMaxRg - 1);
float x = viDeltaaxisL;
float y = viY - viDeltaaxisH;// +objPenLine.Width;
for (int i = 0; i < viMaxRg; i++)
{
if (!f || i % 2 == 0)
{
graph.DrawString(rgsZn[i, 1], objFont, objBrush, x + i * fdeltax, y);
}
else
{
graph.DrawString(rgsZn[i, 1], objFont, objBrush, x + i * fdeltax, y+ objFont.Size);
}
}
}
#endregion
#region Текст по оси Y - Значения по сетке
public void vDrawTextAxYValues()
{
string s = string.Empty;
float f = 0;
float fMax = float.MinValue;
for (int i = 0; i < viMaxRg; i++)
{
s = rgsZn[i, 0];
if (string.IsNullOrEmpty(s)) break;
if (fMax < float.Parse(s)) fMax = float.Parse(s);
}
f = fMax / (float)(viMaxRg-1);
//Пикселей для надписей по оси х
float fdeltay = viY - 2 * viDeltaaxisH;
//Пикселей на один отсчет
fdeltay = fdeltay / (float)(viMaxRg-1);
float y = viY - viDeltaaxisH - objFont.Size;
for (int i = 0; i < viMaxRg; i++)
{
graph.DrawString(((float)(i * f)).ToString("0.00"), objFont, o
bjBrush, viDeltaaxisL - (objFont.Size)*5-5, y - i * fdeltay);
}
}
#endregion
#region Надписи по оси Y - Значения над точкой
public void vDrawTextAxYValuesPoint(int a, int b)
{
string s = string.Empty;
float fMax = float.MinValue;
float fSum = 0;
for (int i = 0; i < viMaxRg; i++)
{
s = rgsZn[i, 0];
if (string.IsNullOrEmpty(s)) break;
fSum += float.Parse(s);
if (fMax < float.Parse(s)) fMax = float.Parse(s);
}
//Пикселей для надписей по оси х
float fdeltax = viX - viDeltaaxisL - viDeltaaxisR;
//Пикселей на один отсчет по х
fdeltax = fdeltax / (float)(viMaxRg - 1);
float x = viDeltaaxisL;
float fdeltay = viY - 2 * viDeltaaxisH;
float y = viY - viDeltaaxisH - objFont.Size;
//Пикселей на одну единицу
fdeltay = fdeltay / fMax;
float fdelta = 0;
for (int i = 0; i < viMaxRg; i++)
{
if (a == 1)
{
if (i % 2 == 0) fdelta = objFont.Size;
else fdelta = 2 * objFont.Size;
}
else
{
fdelta = objFont.Size;
}
if (b == 0)
{
graph.DrawString(rgsZn[i, 0], objFont, objBrush, x + i * fdeltax,
y - (float.Parse(rgsZn[i, 0]) * fdeltay) - fdelta);
}
else
{
s = rgsZn[i, 0];
if (string.IsNullOrEmpty(s)) break;
float fp = float.Parse(s);
fp = (fp * 100) / fSum;
graph.DrawString(rgsZn[i, 0] + "-" + fp.ToString("0.0")+"%", objFont, objBrush, x + i * fdeltax,
y - (float.Parse(rgsZn[i, 0]) * fdeltay) - fdelta);
}
}
}
#endregion
#region Нарисовать круг отступ от краев цвет толщина круга обводки
public void vDravCircle(int deltaaxisL,int deltaaxisR,int deltaaxisH, Color colorpenaxis, int widthpen)
{
//Запоминаем отступы
viDeltaaxisL = deltaaxisL;
viDeltaaxisR = deltaaxisR;
viDeltaaxisH = deltaaxisH;
//Запоминаем цвет осей и толщину
vSetPenColorLine(colorpenaxis);
if (widthpen > 0) vSetPenWidthLine(widthpen);
float a = viY;
float b = 0;
if (viX - (viDeltaaxisL + viDeltaaxisR) < viY - 2*deltaaxisH)
{
a = viX;
b = 1;
}
//Диаметр окружности
if (b == 0)
{
a -= 2*deltaaxisH;
}
else
{
a -= (deltaaxisL + deltaaxisR);
}
//Запоминаем диаметр
viDiamX = a;
//Запоминаем центр окружности
if (b == 0)
{
vfXcirc = deltaaxisL + a / 2;
vfYcirc = viY / 2;
}
else
{
vfXcirc = deltaaxisL+ a/2;
vfYcirc = viY / 2;// +deltaaxisH;
}
//Просто круг ободка
graph.DrawEllipse(objPenLine, vfXcirc - a / 2, vfYcirc - a / 2, a - 1, a - 1);
float fSum = 0;
string s = string.Empty;
for (int i = 0; i < viMaxRg; i++)
{
s = rgsZn[i, 0];
fSum += float.Parse(s);
}
float f = 0;
float fBSum = 0;
//Рисуем секторы
float fDeltaGrad = fSum / 360;
for (int i = 0; i < viMaxRg; i++)
{
s = rgsZn[i, 0];
f = float.Parse(s);
//f в градусах
f = f / fDeltaGrad;
int j = i % br.Length;
float k = f;
if (f < 1) k = 1;
graph.FillPie(br[j], vfXcirc - a / 2 + widthpen / 2, vfYcirc - a / 2 + widthpen / 2,
a - widthpen, a - widthpen, fBSum, k);
fBSum += f;
}
}
#endregion
#region vDravTextCircle
public void vDravTextCircle(int viGde, int viDelta)
{
float fSum = 0;
string s = string.Empty;
for (int i = 0; i < viMaxRg; i++)
{
s = rgsZn[i, 0];
fSum += float.Parse(s);
}
float f = 0;
float fBSum = 0;
float f1Radian = (float)Math.PI / 180;
//Рисуем секторы
float fDeltaGrad = fSum / 360;
for (int i = 0; i < viMaxRg; i++)
{
s = rgsZn[i, 0];
f = float.Parse(s);
//f в градусах
f = f / fDeltaGrad;
int j = i % br.Length;
//Угол в радианах
float fRad = (f + fBSum) * f1Radian;
float fty = 0;
float ftx = 0;
float ftxd = 0;
//if ((i % 2) != 0) ftxd = viDeltaaxisL / 2;
if ((f / 2 + fBSum) < 90 || (f / 2 + fBSum) > 270)
{
if ((f / 2 + fBSum) < 90) ftxd = viDelta/5; else ftxd = viDelta;
ftx = vfXcirc + (viDiamX / 2) * (float)Math.Cos((360 - (f / 2 + fBSum)) * f1Radian) + ftxd;
}
else
{
ftxd = -3 * viDelta;
ftx = vfXcirc + (viDiamX / 2) * (float)Math.Cos((360 - (f / 2 + fBSum)) * f1Radian) + ftxd;
}
if ((f / 2 + fBSum) < 180)
{
fty = vfYcirc - (viDiamY / 2) * (float)Math.Sin((360 - (f / 2 + fBSum)) * f1Radian);
}
else
{
ftxd = -15;
fty = vfYcirc - (viDiamY / 2) * (float)Math.Sin((360 - (f / 2 + fBSum)) * f1Radian) + ftxd;
}
vSetBrush(br[j]);
if (viGde == 1)
{
graph.DrawString(rgsZn[i, 0], objFont, objBrush, ftx, fty);
}
else
{
graph.DrawString(Convert.ToString(i + 1), objFont, objBrush, ftx, fty);
}
fBSum += f;
}
}
#endregion
#region Текст истории
public void vDravTextKeyCircle(bool vfGde)
{
float fSum = 0;
float f = 0;
string s = string.Empty;
for (int i = 0; i < viMaxRg; i++)
{
s = rgsZn[i, 0];
fSum += float.Parse(s);
}
//Сдвиг от круговой диаграммы
float vfSdvig = vfXcirc + viDiamX / 2;
vfSdvig+=(viX - vfSdvig) / 5;
//Высота места для легенды
//На одну строку по высоте отводится - +1 на заголовок
float vfHg = viY / (viMaxRg + 2);
vSetFont("Arial", 12, true);
if (viMaxRg > 100)
{
graph.DrawString("Легенда не может быть размещена", objFont,
Brushes.DarkBlue, vfSdvig + (viX - vfSdvig) / 10, objFont.Size);
}
else
{
//Шрифт в 2 раза меньше места на строку надписи
if (viMaxRg > 15)
{
vSetFont("Arial", (vfHg / 2), true);
}
else
{
if (viMaxRg > 10)
{
vSetFont("Arial", (vfHg / 3), true);
}
else
{
vSetFont("Arial", (vfHg / 6), true);
}
}
if (vfGde)
{
graph.DrawString("Пояснения к графику", objFont, Brushes.DarkBlue,
vfSdvig /*+ (viX - vfSdvig) / 10*/, objFont.Size);
}
else
{
graph.DrawString("Пояснения к графику", objFont,
objBrush, vfSdvig/* + (viX - vfSdvig) / 10*/, objFont.Size);
}
if (viMaxRg > 15)
{
vSetFont("Arial", (vfHg / 2) + 1, true);
}
else
{
if (viMaxRg > 10)
{
vSetFont("Arial", (vfHg / 4)+1, true);
}
else
{
vSetFont("Arial", (vfHg / 7)+1, true);
}
}
for (int i = 0; i < rgsZn.Length / 2; i++)
{
Brush brTxt = null;
int j = i % br.Length;
if (vfGde) brTxt = br[j];
else brTxt = objBrush;
graph.DrawString(Convert.ToString(i + 1), objFont, brTxt, vfSdvig, vfHg * (i + 2));
f = float.Parse(rgsZn[i, 0]);
f = (f * 100) / fSum;
graph.DrawString(rgsZn[i, 0], objFont, brTxt, vfSdvig + 1 * (viX - vfSdvig) / 5, vfHg * (i + 2));
graph.DrawString(f.ToString("0.0") + "%", objFont, brTxt, vfSdvig + 2 * (viX - vfSdvig) / 5, vfHg * (i + 2));
graph.DrawString(rgsZn[i, 1], objFont, brTxt, vfSdvig + 3 * (viX - vfSdvig) / 5, vfHg * (i + 2));
}
}
}
#endregion
#region vDravCircle3D
//Параметры - Отступ от краев по X слева deltaaxisL, от краев по Y справа,
//deltaaxisH - отступа сверху и снизу, толщина диаграммы viH, сдвиг сектора viDx, viDy
public void vDravCircle3D(int deltaaxisL, int deltaaxisR, int deltaaxisH, int viH, int viDx, int viDy)
{
//Запоминаем отступы
viDeltaaxisL = deltaaxisL;
viDeltaaxisR = deltaaxisR;
viDeltaaxisH = deltaaxisH;
float a = viX - (deltaaxisL + deltaaxisR);
//Нужен ли выброс сектора
int viMov = 1;
if (viDx == 0 && viDy == 0)
{
viMov = 0;
}
//Запоминаем диаметр
viDiamX = a;
viDiamY = viY - 2 * viDeltaaxisH;
//Запоминаем центр элипса
vfXcirc = deltaaxisL + a / 2;
vfYcirc = viY / 2;
graph.SmoothingMode = SmoothingMode.AntiAlias;
float fSum = 0;
string s = string.Empty;
for (int i = 0; i < viMaxRg; i++)
{
s = rgsZn[i, 0];
fSum += float.Parse(s);
}
float f = 0;
float fBSum = 0;
float fDeltaGrad = (fSum / (float)360);
SolidBrush objBrush = new SolidBrush(Color.Aqua);
Random rand = new Random(DateTime.Now.Millisecond);
float[] frgZn = new float[viMaxRg];
float[] frgSumGr = new float[viMaxRg];
for (int i = 0; i < viMaxRg; i++)
{
s = rgsZn[i, 0];
frgZn[i] = float.Parse(s);
if (i == 0) frgSumGr[i] = 0;
else frgSumGr[i] = frgZn[i] + frgSumGr[i - 1];
}
//Рисуем диаграмму против часовой стрелки со штриховкой до 90градусав по часовой
//Штриховка убирается каждым следующим сектором от сектора предыдущего
//В первом нарисованном секторе она сохраняетсяна случай сдвига первого по часовой стрелке
for (int i = viMaxRg - 1; i >= 0; i--)
{
if (i != viMaxRg - 1 && fBSum < 90) break;
//f в градусах fBSum в градусах
f = frgZn[i] / fDeltaGrad;
//fBSum = frgSumGr[i] / fDeltaGrad;
if (i == viMaxRg - 1)
{
fBSum = 360 - f;
}
else
{
fBSum -= f;
}
//Для цвета
int j = i % br.Length;
float k = f;
if (f < 1) k = 1;
//objBrush.Color = Color.FromArgb(rand.Next(255), rand.Next(255), rand.Next(255));
if (i != 0)
{
if ((fBSum > 90 && fBSum < 180) || i == viMaxRg - 1)
{
for (int d = 0; d < viH; d++)
{
graph.FillPie(new HatchBrush(HatchStyle.Percent25,
color[j]/*objBrush.Color*/), vfXcirc - a / 2, vfYcirc - viDiamY / 2 + d,
viDiamX, viDiamY, fBSum, k);
}
}
objBrush.Color = color[j];
graph.FillPie(objBrush, vfXcirc - a / 2, vfYcirc - viDiamY / 2,
viDiamX, viDiamY, fBSum, k);
}
}
//Рисуем до 90градусов без первого сегмента в случае необходимости сдвига первого по часовой стрелке
fBSum=0;
for (int i = viMov; i < viMaxRg; i++)
{
//f в градусах fBSum в градусах
f = frgZn[i] / fDeltaGrad;
if (i == 1)
{
fBSum = frgZn[0] / fDeltaGrad;
}
//Для цвета
int j = i % br.Length;
float k = f;
if (f < 1) k = 1;
if (fBSum < 90)
{
for (int d = 0; d < viH; d++)
{
graph.FillPie(new HatchBrush(HatchStyle.Percent25,
color[j]), vfXcirc - a / 2, vfYcirc - viDiamY / 2 + d,
viDiamX, viDiamY, fBSum, k);
}
objBrush.Color = color[j];
graph.FillPie(objBrush, vfXcirc - a / 2, vfYcirc - viDiamY / 2,
viDiamX, viDiamY, fBSum, k);
}
else
{
break;
}
fBSum += f;
}
//Рисуем сдвинутый сектор при необходимости
if (viMov == 1)
{
f = frgZn[0] / fDeltaGrad;
fBSum = 0;
float k1 = f;
if (f < 1) k1 = 1;
for (int d = 0; d < viH; d++)
{
graph.FillPie(new HatchBrush(HatchStyle.Percent25, color[0]),
vfXcirc - a / 2 + viDx, vfYcirc - viDiamY / 2 + d - viDy,
viDiamX, viDiamY, fBSum, k1);
}
objBrush.Color = color[0];
graph.FillPie(objBrush, vfXcirc - a / 2 + viDx, vfYcirc - viDiamY / 2 - viDy,
viDiamX, viDiamY, fBSum, k1);
}
}
#endregion
#region vDravTextCircle
public void vDravTextCircle1(bool vfGde)
{
float fSum = 0;
string s = string.Empty;
for (int i = 0; i < viMaxRg; i++)
{
s = rgsZn[i, 0];
fSum += float.Parse(s);
}
float f = 0;
float fBSum = 0;
float f1Radian = (float)Math.PI / 180;
float fDeltaGrad = fSum / 360;
for (int i = 0; i < viMaxRg; i++)
{
s = rgsZn[i, 0];
f = float.Parse(s);
//f в градусах
f = f / fDeltaGrad;
int j = i % br.Length;
//Угол в радианах
float fRad = (f + fBSum) * f1Radian;
float fty = 0;
float ftx = 0;
float fSin=(float)Math.Sin((360 - (f / 2 + fBSum)) * f1Radian);
float fCos=(float)Math.Cos((360 - (f / 2 + fBSum)) * f1Radian);
float c = (float)Math.Sqrt((viDiamX / 2 * viDiamX / 2 * viDiamY / 2 * viDiamY / 2) /
(viDiamY / 2 * viDiamY / 2 * fCos * fCos + viDiamX / 2 * viDiamX / 2 * fSin * fSin));
c -= 3 * objFont.Size;
if (c < 0) c = 0;
ftx = c * fCos;
fty = c * fSin;
ftx = vfXcirc + ftx;
fty = vfYcirc - fty;
if (vfGde)
{
graph.DrawString(Convert.ToString(i + 1), objFont, objBrush, ftx, fty);
}
else
{
graph.DrawString(rgsZn[i, 1], objFont, objBrush, ftx, fty);
}
fBSum += f;
}
}
#endregion
}
}
В начало
Параграф 2. Чуточку пояснений
Шаг первый при рисовании диаграммы - Создаем класс:
PaitCl clPaint = new PaitCl();
При этом в конструкторе можно передать некоторые параметры.
Шаг второй - передаем массив значений для отображения в класс.
Шаг третий - передаем размеры холста.
Шаг четвертый - передаем фон холста
Шаг пятый -передаем цвет шрифта надписей имя, размер, стиль.
Шаг шестой - рисуем график (в функцию для рисования могут быть переданы доп. параметры: отступ осей x слева, x справа ,y от краев холста, толщина диаграммы, вынос сектора...
Шаг седьмой - забираем Bitmap из класса (clPaint.bmpGet()) и отображаем, например в PictureBox.
Молчанов Владислав 1.12.2008г.
В начало страницы
На главную страницу
К началу книги
|