Смекни!
smekni.com

Разработка элемента управления для отображения векторных карт (стр. 3 из 6)

private bool flRec; //рисовать прямоугольник выделения

private int oldX; //координаты нажатия кнопки мыши

private int oldY;

private int curX; //текущееположениемыши

private int curY;

private double oldDx; //староесмещениекоординатныхосей

private double oldDy;

public delegate void MapLoadEndDelegate(); //определениеделегата

public event MapLoadEndDelegate MapLoadEnd; //определениесобытия

}

Метод public void FileOpen(string Pth) предназначен для открывания файла векторного изображения и получении координат замкнутых областей. В начале создается новый экземпляр класса MyMap, устанавливается начальный масштаб и коэффициенты координатных осей. Затем идёт открытие потока для чтения где параметром вызова выступает строка с полным путем к файлу.


StreamReader StrmR = new StreamReader(Path);

Чтение из потока происходит по строчно, строка записывается в переменную str которая и будет использоваться для анализа, выделения команд и координат замкнутых областей. При поступлении набора символов предшествующего массивам координат замкнутых областей флаг flag устанавливается в значение true что говорит о том что начинается считывание координат замкнутых областей. Далее считывается следующая строка и происходит выделение координат. Пока не достигнут конец строки или не найден один из командных символов происходит выделение координат. Из строки по символьно читаются цифры до появления пробела что говорит об окончании значения координаты. Ведётся подсчёт считанных чисел для определения вида координаты по оси X или по оси Y. Не чётные числа означают координаты по оси X чётные числа - координаты по оси Y. Затем создается экземпляр типа PointD с полученными координатами и происходит добавление в экземпляр класса PathD. То есть формируется замкнутая область. Процесс считывания и добавления координат, формирование замкнутая области происходит до того как встречается следующая командная строка. В этот момент сформированная замкнутая область добавляется в коллекцию областей, передаётся в экземпляр класса MyMap а флаг flag устанавливается в значение false сигнализируя о том что чтение координат и формирование области закончено. Далее процесс повторяется пока не будет достигнут конец файла. После чего поток закрывается, ресурсы высвобождаются. Далее вызываются методы SetScaleToView(this.Height,this.Width) и SetXYtoView() экземпляра класса MyMap для масштабирования и расположения изображения в пределах окна. После чего если определёно то вызывается функция сопоставленная событию окончания чтения файла. Алгоритм чтения координат из файла представлен на блок-схеме Рис 3.4.

Метод private void CntrIm_MouseDown object sender, System.Windows.Forms.MouseEventArgs e) срабатывает когда происходит нажатие кнопки мыши. При этом flag устанавливается в значение true что означает кнопка нажата, и запоминаются текущие координаты мыши и смещение координатных осей.

Метод private void CntrIm_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) срабатывает когда происходит событие отпускание кнопки мыши. При этом flag устанавливается в значение false.

Метод private void CntrIm_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) срабатывает когда происходит передвижение мыши и запоминаются текущие координаты мыши. Необходимые для отрисовки прямоугольника выделения.

Метод public void ScaleToPoint(int crX,int crY,double sclN) предназначен для изменения масштаба изображения на заданную величину sclN в точку int crX,int crY.

Метод public void MovePoint(int oldx,int oldy, int crx,int cry) предназначен для перемещения изображения из точки с координатами oldx, oldy, в точку с координатами crx, cry.

Метод public void ScaleToRctangle(int oldx,int oldy,int crX,int crY) предназначен для вычисления масштаба для увеличения выделенной области до размеров экрана. Размеры выделенной области определяются первой: oldx,int oldy, и последней точкой int crX,int crY



Рис 3.4 Блок-схема чтения координат из файла


Метод public void VeiwInWindow() предназначен для показа изображения в окне элемента управления. В нем вызываются методы SetScaleToView(this.Height,this.Width) и SetXYtoView() экземпляра класса MyMap для масштабирования и расположения изображения в пределах окна.

Метод RealScale() предназначен для отображения изображения в натуральную величину. Реализовано через установку свойства экземпляра класса MyMap Scale=1 и вызова метода SetXYtoView().

Свойство public bool VeiwRect предназначено для установки значения поля flRec, разрешение или запрещение отрисовки прямоугольника выделения.

Метод public void Allocate(int nPth,int type) предназначен для выделения области указанной в значением параметра nPth, и тип выделения type путём вызова метода Allocate(int nPth,int type) экземпляра класса MyMap.

Метод public void SetClrPath (int NPth,Color Clr) предназначен для установки области с номером NPth цвета окраса Clr. Путём вызова метода SetClrPth(NPth,Clr) экземпляра класса MyMap.

Метод public Color GetClrPath(int NPth) предназначен для получения цвета окраса области с номером NPth.(пример: mapD.AllPaths[NPth].ColorP)

Метод private void CntrIm_SizeChanged(object sender, System.EventArgs e) срабатывает когда изменяются размеры элемента управления. В нем вызываются методы SetScaleToView(this.Height,this.Width) и SetXYtoView() экземпляра класса MyMap для масштабирования и расположения изображения в пределах окна.

Метод protected override void OnPaint(PaintEventArgs e) является перегруженный методом вызываемым при перерисовке элемента управления. Чтобы получить изображение нам необходимо нарисовать все замкнутые области, чтобы нарисовать замкнутую область нам необходимо для данной области простись по всем точкам соединяя каждую точку с последующей. Первый цикл осуществляет перемещение по набору областей а второй цикл осуществляет переход от точки к точке внутри области выбранной в предыдущем цикле. Через методы классов мы получаем доступ к координата конкретной точки.

tmP[j].X=Convert.ToInt32((mapD.AllPaths[k].PathPoints[j].X-

mapD.DX)*mapD.KX*mapD.Scale);

tmP[j].Y=Convert.ToInt32((mapD.AllPaths[k].PathPoints[j].Y-

mapD.DY)*mapD.KY*mapD.Scale);

Эти координаты конвертируются в текущую систему координат и конвертируются из типа double в тип int и заносятся в экземпляр типа Point который находится в массиве длинна которого равна количеству точек в текущей замкнутой области. Когда все координаты текущей замкнутой области перенесены через экземпляр класса PaintEventArgs осуществляется доступ к экземпляру класса Graphics с помощью которого и осуществляется рисование на элементе управления. Сначала заливается текущая облать выбранным стилем и цветом, затем осуществляется доступ к кисти которым должна быть отрисована данная область. Доступ осуществляется через свойство экземпляра класса MyMap AllPen с указанием номера области, то есть соответствующему ей перу.

SolidBrush dBr = new SolidBrush(mapD.AllPaths[k].ColorP);

e.Graphics.FillPolygon(dBr,tmP); Pen tPen;

if(mapD.AllPen[k]==null)

{

tPen=new Pen(Color.Black,1);

}

else

{

tPen=mapD.AllPen[k];

}

e.Graphics.DrawLines(tPen,tmP);

Если кисть не определена то отрисовка ведётся пером по умолчанию. После чего процесс повторяется для других областей. После этого осуществляется вывод в центре области порядкового номера этой области. Процесс доступа к точке центра области хранимой в каждом экземпляре PathD производится через методы и свойства экземпляра класса MyMap. Печать строки осуществляется с помощью метода экземпляра класса Graphics DrawString. Затем с помощью метода экземпляра класса Graphics DrawLines выводятся границы элемента. После проверки соответствующих булевых переменных происходит вывод прямоугольника выделения.

if (flRec==true&&flag==true)

{

Pen myP= new Pen(Color.Blue,1);

e.Graphics.DrawLine(myP,oldX,oldY,oldX,curY);

e.Graphics.DrawLine(myP,oldX,oldY,curX,oldY);

e.Graphics.DrawLine(myP,curX,oldY,curX,curY);

e.Graphics.DrawLine(myP,oldX,curY,curX,curY);

}

3.5 КлассAutoColor

public class AutoColor

{

public PathD [] msPth; //коллекция замкнутых областей

public Color [] msClr; //массив цветов областей

public AutoColor() //конструктор по умолчанию

{ msPth=null;

msClr=null;

}

}

Конструктор public AutoColor(PathD [] Pth) параметром для которого является коллекция областей для которой будет производиться автоматическое раскрашивание. Раскрашивание будет производиться по принципу оптимального использования цветов. В начальный момент времени создается массив типа Color в который будут заноситься цвета для раскрашивания соответствующих областей. Далее вызывается функция private int[,] GetMsGr() которая предназначена для создания матрицы пограничных областей. Строки и столбы этой матрицы представляют собой замкнутые области а узлы матрицы границы между областями.

Например у нас есть 4 ре области как показано на Рис 3.5.

Рис 3.5 Пример расположения областей.

Значит матрица пограничных областей будет выглядеть следующим образом

0 1 1 0

1 0 1 0

1 1 0 0

0 0 0 0


То есть если деве области имеют общую границу то в узле матрицы номер сроки и номер столбца которого соответствует граничащим областям будет находится 1, если же общей границы нет то в узе остаётся 0. Сам алгоритм проверки на существование общей границы таков: Первый цикл перебирает области которые нужно сравнить 2цикл, вложенный в него перебирает координаты которые сравнивает и запоминает их в переменный которые будут использоваться при сравнении. 3ий цикл вложенный во второй перебирает области с которыми надо сравнить исключая текущую область. 4ый вложенный цикл в 3ий перебирает сами координаты. Если координаты текущей точки текущей области совпадают со сравниваемыми координатами данной области то в узлах матрицы с соответствующими номерами столбцов и срок записывается 1. И так процесс повторяется для всех областей. Функция возвращает заполненную матрицу. Далее представлена часть кода функции GetMsGr() заполняющая матрицу

for (int i=0;i<msPth.Length;i++) //1ывй цикл

{

for(int j=0;j<msPth[i].Length;j++) //2ойвложенныйцикл

{

x1 = msPth[i].PathPoints[j].X; //запоминание координат точки для сравнения

y1 = msPth[i].PathPoints[j].Y;

for (int k=0;k<msPth.Length;k++) //3ийвложенныйцикл

{

for(int l=0;l<msPth[k].Length;l++) 4ыйвложенныйцикл

{

if(i!=k)

{

_x1 = msPth[k].PathPoints[l].X;

_y1 = msPth[k].PathPoints[l].Y;

if(x1==_x1&&y1==_y1) //сравнение координат текущей

{ //точки с запомненными

ms[i,k]=1;

}

Далее вызывается рекурсивная функция Run(i,ref mss); где параметрами являются i-номер области с которой надо начинать расчёт окраски, ref mss ссылка на массив пограничных объектов. Алгоритм работает следующим образом. В начале проверяется окрашен уже данная область или нет. Номер цвета содержится в диагонали матрицы. Если не окрашена область, то ищется цвет не принадлежащий окружающим эту область областям. Тесть выбирается jый цвет затем проходя по сроке ищет области которыми граничит и найдя такую область сравнивает текущий цвет с цветом этой области если совпадают то flag устанавливается из true в false а поиск продолжается по остальным областям. Если же нет то переход к следующей пограничной области. Если для данного j по всем граничащим областям не нашлось равного то данное число записывается как цвет данной области. Затем для всех областей в которые ёще не переходили и которые граничат с данной областью запускается рекурсивная функция Run(i,ref ms); а в узлы где номер столбца это область текущая а строка это область куда перейдём и наоборот записывается 2. Рекурсия повторяется. Пример массива на разных этапах при распределении цветов: