1. Контур сельскохозяйственных угодий (сх/контур) – часть земель, используемых или предназначенных для производства сельскохозяйственных культур, сенокошения и выпаса сельскохозяйственных животных (пашня, сенокосы, пастбища, залежь, многолетние насаждения) и ограниченная естественными природными или искусственными объектами антропогенного характера (дорогами, строениями, лесополосами, оврагами лесными массивами и водными объектами).
2. Сельскохозяйственный полигон (полигон) – часть контура сельскохозяйственных угодий, занятая однородными сельскохозяйственными культурами (имеет однородную спектральную плотность на космоснимке).
3. Внутрихоз – землеустроительный план сельскохозяйственного предприятия, оформленный в виде землеустроительного плана масштаба 1 : 10 000 или картограммы масштаба 1: 25 000.
1. Оцифровка картматериала производится в ГИС MapInfo 9.5 с соблюдением всех норм топологии (т.е. не допускаются петли, недоводы, пересечение контуров и т.д.). Контроль топологии осуществлять визуально и встроенными средствами ГИС MapInfo.
2. Оцифровке подвергаются все сх/контура, изображенные на растровой подложке масштаба 1 : 10 000 c использованием картограмм внутрихозов масштаба 1 : 25 000. Внутрихоз на каждое хозяйство масштаба 1: 25 000 прилагается в бумажном виде и используется в качестве справочного материала.
3. Оцифровку сх/контуров производить с размером зума экрана не более в 1см 20 м. В противном случае вероятна некорректность (потеря точности) при определении площади контура. Одной из целей указанной работы является точное определение площади контуров.
4. Имя векторного слоя, в котором происходит оцифровка KLG_KZE_PSN, где N может принимать значения 1.. 99. Максимальное значение N соотв. наиболее свежей (последней) версии оцифровки. Данная маркировка приведена только для хозяйств Козельского района (KZE).
5. В случае, если граница спектральной плотности космоснимка сильно отличается от границы контура с внутрихоза 10 000, приоритет отдавать границе контура по космоснимку (по границе спектральной плотности). При несущественных отличиях цифровать по границе контура c внутрихоза масштаба 1 : 10 000.
6. Все хозяйства района оцифровываются в одном векторном слое KLG_KZE_PSN площадными объектами.
7. При наличии нескольких участков («полигонов») с разной спектральной плотностью на одном сх/контуре необходимо произвести «нарезку» полигонов внутри сх/контура по спектральной плотности. Т.е. на одном сх/контуре может находиться несколько полигонов с разной спектральной плотностью.
8. Маркировку сх/контуров (номер контура) брать с прилагаемой бумажной копии внутрихоза масштаба 1 : 25 000. В качестве справочной информации можно использовать номер контура с растровой подложки масштаба 1 : 10 000, но он не всегда может совпадать с номером контура с 25 –и тысячного масштаба. В этом случае приоритет отдавать номеру с 25 –и тысячного масштаба.
9. Номер (код) контура заноситься в поле F_ID векторизуемого слоя KLG_KZE_PSN. В поле FARM_ID заносится код хозяйства в соответствии с прилагаемой справочной таблицей хозяйств Козельского района (5 –и значный код). Таким образом, совокупность двух этих полей дает уникальный код каждого сх/контура.
Остальные поля не заполняются.
10. Полностью оцифрованные хозяйства маркировать на общей сборке надписью наименования хозяйства на зеленом фоне, еще не оцифрованные – на красном, которые в работе – на желтом.
Справочная таблица хозяйств Козельского района
|
Код хоз-ва |
Наименование хозяйства |
|
10 001 |
ОАО ДРУЖБА (с.Волконское) |
|
10 002 |
ЗАО КОЗЕЛЬСКОЕ МОЛОКО/отд.ЗАВЕТЫ ИЛЬИЧА (с.Попелево) |
|
10 003 |
ЗАО КОЗЕЛЬСКОЕ МОЛОКО/отд.ЗАРЯ (с.Покровск) |
|
10 004 |
КСП КАМЕНСКОЕ(бывш.им.Кирова) |
|
10 005 |
СПК РУСЬ (бывш.колхоз им.Ленина) |
|
10 006 |
СЕРЕНА (бывш.им.Мичурина, разд.на Серена+Торбеево) |
|
10 007 |
ПХ монастыря Оптина Пустынь (Фроловское) (бывш.к-з Октябрь) |
|
10 008 |
ЗАО КОЗЕЛЬСКОЕ МОЛОКО/отд.ПЛЮСКОВО |
|
10 009 |
КСП КИРЕЕВСКОЕ (с.Киреевское) |
|
10 010 |
КСП РОДИНА (Сенино) |
|
10 011 |
СХА НИВА (Подборки) |
|
10 012 |
КСП ПОБЕДА (Прыски) |
|
10 013 |
ООО ГЕЯ |
|
10 014 |
ЗАО КОЗЕЛЬСКОЕ МОЛОКО/отд.ПЛОДОВОД |
|
10 015 |
ООО КРАСНЫЙ КОМБИНАТ |
|
10 017 |
ПХ СОСЕНСКОЕ |
|
10 018 |
ТОРБЕЕВО (бывш.им.Мичурина, разд.на Серена+Торбеево |
|
10 019 |
СПТУ-28 |
|
10 020 |
СПТУ-14 |
Форма этой утилиты имеет следующий вид:
Жмём кнопку OK. Утилита запишет координаты точек в указанные выше поля атрибутивной таблицы X/Y:

Ну, собственно, и всё. Поставленную задачу выполнили. Осталось, при желании, создать макет нашей карты, который может выглядеть приблизительно так (меню Окно>Новый Отчёт):

Если во фрейме списка на макете карты размер шрифта покажется мелковатым, то этот момент можно подправить, нажав в списке мышкой по заголовку таблицы и выбрав в контекстном меню Стиль текста:

© Simashkov.2012
07.04.2012 г.
Калькулятор Дальностей>Выполнить :

… и далее задаём опции приблизительно так, как указано на рисунке ниже:
![]() |
Небольшой комментарий. По логике задачи будем промерять расстояния от нас. пунктов (слой Klg_RayCenter) до аэродромов (Airports). Поскольку в нашем примере 3 объекта, до которых нужно узнать расстояния, то в поле Количество дальностей и указываем именно такое значение. Для генерации списка дальностей жмём на кнопку Вычислить, и в случае необходимости сохранить результаты , естественно кликаем по соответствующей кнопке. Результат измерений отобразиться в списке слева в колонке Дальность. |
Теперь нам нужно будем обработать полученные результаты — сгруппировать (просуммировать) расстояние до каждого аэродрома. Проще всего это будет сделать с помощью соотв. запроса по меню Запрос>SQL — запрос и набрать его так, как показано на сл. картинке (самое важное здесь — указать группировку по полю Цель для нашего примера):

Апофеоз всей нашей работы — табличка с суммами расстояний от населенных пунктов до 3-х рассматриваемых в качестве альтернатив площадок :

Не надо быть большим специалистом по выбору локализаций объектов гражданской авиации, чтобы понять, что аэропорт Грабцево (в случае нашего примера) по критерию минимальной удаленности от основных нас. пунктов региона выглядит наиболее предпочтительно.
Как решить аналогичную задачу в ArcGIS, можно посмотреть здесь
© Simashkov.2014
07.12.2014 г.
{
return true;
}
else
{
return false;
}
}
… можно написать такой простой код:
public
static bool TruOrFls(int i)
{
return (i > 0);
}
2. Для определения, является ли целое число чётным или нечётным, можно использовать сл. метод:
public static bool IsNechet(int i)
{
int result;
Math.DivRem(i, 2, out result);
return (result==1);
}
3. Простой класс для Шаблона «Одиночка» (Singleton) для создания форм:
namespace
MySpace
{
public static class SingletonForm
{
private static Dictionary forms = new Dictionary();
public static Form ShowInstance(Type t)
{
if (!forms.ContainsKey(t)) {
Form f = (Form)Activator.CreateInstance(t);
f.Disposed += new EventHandler(f_Disposed);
forms.Add(t, f);
}
forms[t].Show();
forms[t].Activate();
return forms[t];
}
static void f_Disposed(object sender, EventArgs e)
{
forms.Remove(sender.GetType());
}
}
}
Пример использования:
public void btnsprTIP_Click(System.Object sender, System.EventArgs e)
{
SingletonForm.ShowInstance(typeof(frmMyForm));
}
4. Для «отлавливания» неверно введённого символа в сетке(DataGridView) можно использовать событие DataError:
public
void MyDtg_DataError(object sender, DataGridViewDataErrorEventArgs anError)
{
int ColIndx = (int)anError.ColumnIndex;
string ColHT = MyDtg.Columns[ColIndx].HeaderText;
Utils.Mess(» » + ColHT + » !»);
MyDtg.CurrentCell.ErrorText = » » + ColHT;
}
5. Помещайте формы, классы, отчёты и т д. проекта в соответствующие подкаталоги с именами, например, FRM, CLS, RPT и т.д. Такая систематизация существенно облегчит вашу жизнь при работе с большими проектами. Мешанина из классов, форм, отчётов и пр. в одном подкаталоге вряд ли пойдёт на пользу качеству вашего проекта.
6. Если нужно постоянно обращаться к какому-то объекту ( или что-то возвращать из метода без передачи параметра внутрь его), то такую функцию удобно осуществлять с помощью аксессора get. Например, сл. код возвращает текущую строку в DataGrid View:
public DataGridViewRow GetCurrentRowOb
{
get {return this.MyDtg.CurrentRow;}
}
К такому методу можно обращаться просто как к переменной.
7. Вы можете назначить свою обработку какого-либо события в конструкторе сл. образом:
public frmMain()
{
InitializeComponent();
/*Альтернативная обработка события */
this.txtHr.KeyPress += new KeyPressEventHandler(this.ObrabKey);
}
В приведённом примере назначаем метод обработки ObrabKey событию KeyPress
8. Технология LINQ может существенно сократить количество ваших клацаний по клавиатуре. Например сл. код возвращает отсортированный массива:
public static string[] GetStr
{
// …
get
{
string[] ar = new string {«one», «two», «three», … «nine»);
};
return ar;
}
/
*Сортируем массив
…
*/
public static IEnumerable SortedList
{
get
{
IEnumerable sort = GetStr.OrderBy(a => a.j);
return sort;
}
}
9. Несложные классы (особенно если используется их большое количество экземпляров) лучше оформлять в виде структур — ключевое слово struct. Структура, в отличии от класса, является значимым типом. Экономия ресурсов, в этом случае, может оказаться весьма существенной.
10. Довольно часто приходиться итерировать объекты, которые не поддерживают интерфейс IEnumarable. Чтобы избежать это ограничение, существует специальная конструкция — yeild. Ниже приведён пример, как можно проитерировать коллекцию упр. элементы на главной форме:
class
Num : IEnumerable
{
frmMain MyF = GlobalVar.MainForm;
public System.Collections.IEnumerator GetEnumerator()
{
yield return MyF.Panel1;
yield return MyF.Panel2;
yield return MyF.Panel3;
yield return MyF.panel6;
yield return MyF.GroupBox1;
yield return MyF.groupBox2;
yield return MyF.GroupBox3;
yield return MyF.TableLayoutPanel1;
yield return MyF.pictureBox1;
}
Вот теперь можно пробежаться в цикле -применение в вызывающей стороне:
foreach
(Control cob in new Num())
{
cob.Anchor = AnchorStyles.Right;
}
11. Использование конструкции using ( …) { … } гарантирует применение метода .Dispose() — освобождение объекта , например:
using (SqlCommand cmd = new SqlCommand(strSQL, GlobalVar.conn))
{
//
Здесь что-то делаем с объектом
cmd …
}
// Это нужно делать, если не использовать using (…) { }
// cmd.Dispose();
12. При работе с базами данных обязательно напишите класс с методами создания соединения с БД и его тестированием, что-то вроде этого:
static class clsConn
{
// Создание соединения …
public static void CreateConn(string strmydir)
{
try
{
GlobalVar.conn = new SqlConnection(ConnectStringBuild);
GlobalVar.conn.Open();
}
catch (Exception)
{
Utils.Mess(» Ошибка!»);
}
}
// Тестирование соединения …
public static bool TestConn
{
get
{
try
{
using (SqlConnection testconn = new SqlConnection(ConnectStringBuild))
{
testconn.Open();
return (testconn.State == ConnectionState.Open);
}
}
// …
catch (SqlException)
{
return false;
}
catch (InvalidOperationException)
{
return false;
}
}
}
// Создание строки подключения к БД …
public static string ConnectStringBuild
{
get
{
string s = «Data Source=» + My.Settings.Default.ServerName + @»» + My.Settings.Default.SQLServerName + «;»;
return @s += «Initial Catalog=» + My.Settings.Default.BaseName + «;Integrated Security=True»;
}
}
13. Включите обработку ошибок в стартовый модуль вашей программы. Выше него ошибка «не поднимется»( выше только Господь Бог :-). Что-то вроде этого:
sealed
class mdlMain
{
[STAThread]
public static void Main(string[] args)
{
try
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
GlobalVar.MainForm = new frmMain();
Application.Run(GlobalVar.MainForm);
}
catch (ArgumentNullException ane)
{
MessageBox.Show(ane.Message, » Main-ArgumentNullException»);
}
catch (FormatException fex)
{
MessageBox.Show(fex.Message, » Main-FormatException»);
}
catch (NullReferenceException nre)
{
MessageBox.Show(nre.Message, » Main-NullReferenceException»);
}
catch (InvalidCastException ice)
{
MessageBox.Show(ice.Message, » Main-InvalidCastException»);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message , » o Main»);
}
}
}
14. Если в программе постоянно приходиться обрабатывать неизменяемый массив строк, то инициализацию такого массива очень удобно оформить с помощью аксессора get (см. Совет 6), что-то вроде этого:
private
static string[] GetStringArr
{
get
{
string[] ars = new string[] {
«one » ,
«two «,
«three «,
…
«nine «
};
return ars;
}
}
Тогда подсчитать, например, количество элементов в массиве очень просто:
int RecCount1 = GetStringArr.Count();
Или, обращение к j-му элементу массива:
string s = GetStringArr[j-1];
15. Довольно часто в коде нужно контролировать — является ли значение пустым, и вернуть, ну допустим, значение нуль для типа float. Осуществить такую проверку можно с помощью такого нехитрого метода:
public static float CheckIt(object par)
{
return (Convert.ToSingle(Convert.IsDBNull(par) ? 0 : par));
}
16. Если нужно знать, в каком столбце сетки DataGridView пользователь завершил редактирование ячейки, то можно использовать событие _CellEndEdit:
public
void MyDtg_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
// Узнаём имя столбца …
string ColName = MyDtg.Columns[e.ColumnIndex].Name;
try
{
switch (ColName)
{
case(«Col1»):
/* Здесь что-то делаем … */
break;
case(«Col2»):
// …
break;
case(«Col3»):
}
}
17. Чтобы ‘пробежаться’ по всем контролам в панели, и отловить, ну скажем, метки (Label) можно использовать такой код:
foreach (Control cob in this.panel
1
.Controls)
{
if (cob is Label)
{
/* Здесь что-то делаем с контролом типа Label */
}
}
18. К строковой переменной можно смело «приклеивать» целочисленные переменные. Среда CLR поймёт такое преобразование без метода ToString(). Это особенно бывает удобно при формировании SQL-запросов в виде строк, что-то вроде этого:
int i=0;
string
sSQL=»Update Itogi SET Area=@area where kod=» + (i + 1);
19. ‘Склеивать’ строки лучше специально созданным для этого методом Concat для переменных типа string:
string s1 = «one»;
string s2 = «two»;
string s3 = «three»;
// Можно делать так:
string sAll = s1+s2+s3;
// … но грамотнее так:
string sAll = string.Concat(s1,s2,s3);
20. Программисты как-то недооценивают удобство метода Format для строк при формировании SQL-запросов . Например, вместо того, чтобы писать что-то вроде этого:
//
Можно делать так
:
string strUpdate = «Update Customers SET Balance=@Balance Where CustID=» +ID +» and SocialID=» + SocID;
… лучше написать такой код:
// Грамотнее так:
string strUpdate = «Update Customers SET Balance=@Balance Where CustID=»;
string strSQLUpdate = string.Format(«{0}{1} and SocialID={2}», strUpdate, ID, SocID);
21. Иногда бывает нужно узнать индекс элемента в массиве, ну например, в цикле foreach. Сделать это можно сл. образом:
// Есть массив строк …
private
static string[] GetStr
{
get
{
string[] ars = new string[] {
«one » ,
«two «,
«three «,
…
«nine «
};
return ars;
}
}
//В вызывающей стороне:
// Конечно, можно использовать счётчик …
int counter = -1;
foreach (string s in GetStr)
{
++counter;
…
}
// … но изящнее так :
private static void Sub()
{
foreach (string s in GetStr)
{
//Узнаём индекс элемента s в массиве …
int i = Array.IndexOf(GetStr, s);
…
}
}
22. Везде, где можно, предпочтительнее использовать типизированные коллекции, вместо классических массивов. Основные преимущества такого подхода заключаются в двух фактах: во-первых, коллекции позволяют не заботиться о контроле за выходом индекса за установленный размер (пресловутое Index Out of Range), а во-вторых, в них можно хранить (в отличии от нетипизированных списков) элементы одного типа. Итак, вместо использования скажем:
string[] ars = new string[6];
… предпочтительнее использовать типизированный список List:
List ars = new List();
Небольшая ремарка. Вообще, на мой взгляд, в связи с появлением начиная , по-моему, с .NET Framework 2.0 типизированных коллекций, классические массивы можно считать коллекциями устаревшего типа по причинам, указанным выше
23. Если в метод надо передавать много-много всяких входных параметров, то вместо такого «баяна» предпочтительнее передавать структуру.
Например, вместо использования некоего метода XYZ
static void XYZ(int a, int b,int c, string d, string e)
.
.. можно сначала определить структуру:
struct ABC
{
public int a,b,c;
public string d,e;
public ABC (int _a, int _b, int _c, string _d, string _e)
{
a=_a; b=_b; c=_c; d=_d; e=_e;
}
}
… а затем передавать её в метод :
static void XYZ(ABC mystru)
Вызов такого метода станет гораздо более изящным:
/*
Определяем экземпляр структуры
ABC */
ABC MyStru = new ABC (1,2,3,»one», «two»);
/*Вызываем метод
XYZ */
XYZ(MyStru);
24. Довольно часто программисты пользуются методом Parse для конвертации строковых величин в другие типы, что-то вроде этого:
int j= int.Parse (MyVal.ToString());
Однако, в случае неудачи такой метод выбросит исключение. Для написания устойчивого кода предпочтительнее пользоваться метод TryParse, приблизительно так:
int j; /* Вернёт значение j=0, даже если метод TryParse потерпит неудачу */
bool bVal = int.TryParse(MyVal.ToString(), out j);
25. Самый подходящий элемент для отображения содержания базы данных — это конечно же DataGridView, упрощенно говоря, сетка данных. Но после завершения редактирования данных пользователем в такой сетке встаёт задача — как передать изменения в базу данных? Одно из решений такой задачки состоит в переписывании (в цикле естественно) значений ячеек сетки DataGridViewCell в значения объекта DataRow , привязанного к сетке объекта DataTable набора данных DataSet . Тут, правда, надо хорошо разбираться в идеологии объектной модели доступа к данным ADO. NET. Затем значения DataRow конкретного столбца переписываем SQL-конструкцией Update непосредственно в базу данных. Все циклы здесь можно прогонять конструкцией foreach
26. Иногда возникает сл. ситуация. На форме есть куча однотипных элементов WinForms, одно и тоже событие которых обрабатывается одинаково. Как пример, есть несколько элементов TextBox, для которых событие, ну скажем, KeyPress обрабатывается одним и тем же методом.
Тогда, вместо такого забойного кода …. :
// Textbox1 …
public void txtbox1_KeyPress(object sender, KeyPressEventArgs e)
{
ObrabKeyPress(sender, e);
}
// Textbox2 …
public void txtbox2_KeyPress(object sender, KeyPressEventArgs e)
{
ObrabKeyPress(sender, e);
}
…
// TextboxN …
public void txtboxN_KeyPress(object sender, KeyPressEventArgs e)
{
ObrabKeyPress(sender, e);
}
… можно сначала определить массив TextBox’ов :
private TextBox[] RetTBox
{
get
{
TextBox[] tba = new TextBox []{ txtBox1, txtBox2, … , txtBoxN };
return tba;
}
}
… а затем, скажем в конструкторе формы, прокрутить такой цикл :
/* Добавляем свой обработчик контроля нажатия клавиш */
foreach (TextBox tb in RetTBox)
tb.KeyPress += new KeyPressEventHandler(ObrabKeyPress);
27. У объекта ADO.Net Reader есть один весьма полезный метод — HasRows. Он возвращает значение true, если в запросе есть данные.
Проконтролировать наличие ‘пустого’ Reader’а в это случае становиться довольно легко:
using (SqlCommand SelCustoms = new SqlCommand(sSel, conn2))
{
rReadCustomer = SelCustoms.ExecuteReader();
//Нет записей
о заказчиках
! Прекращаем читать .. if (!rReadCustomer.HasRows) return 0.0f;
// Пробежимся по всем записям Заказчиков …
while (rReadCustomer.Read())
{
int tip = rReadCustomer.GetInt32(0);
// … Здесь что-то читаем Reader’ом
}
04.08.2013
28. Хорошей альтернативой созданию параметров в простых SQL-запросах (объект Parameters) может стать использование строки запроса методом string.Format (см. Совет 20 ), что-то вроде этого:
string sSQL = string.Format(«Select * From Customers where CustomerID={0}», CustID);
SqlCommand cmd = new SqlCommand(sSQL, conn2)
cmd. ExecuteScalar();
Объём кода при этом значительно сокращается
—
необходимость описывать параметр
,
его тип и значение просто отпадает.
04.08.2013
29. Приступая к созданию своего первого более-менее сложного проекта, не забудьте создать класс для размещения в нём всевозможных мелких вспомогательных утилит. Фактически, наличие такого класса (как правило с именем Utils), стало стандартом для проектирования информационных систем на С#. Получиться что-то вроде аналог ящика для инструментов, из которого вы сможете время от времени доставать нужное (по контексту ситуации) приспособление.
04.12.2013
30. Создание глобальных переменных, видимых из любой части программы, является одним из стандартных положений для разработчика любого уровня. Чаще всего, такая необходимость связана с использованием каких-то глобальных настроек программы. Одним из решений этой задачи является использование настроек — пространство имён My.Setting . Тогда достаточно будет написать, ну скажем в классе Utils (см. Совет 29), простой метод для ‘выдёргивания’ значения этой настройки, что-то вроде этого (в приведённом ниже примере, если уж рассматривать совсем конкретный случай, просто взят год, принятый по умолчанию):
public static int GetGodSetting
{
get {
return (int.Parse)(My.Settings.Default.god);
}
}
В любом месте программы для загрузки года, принятого в настройках по умолчанию, можно использовать такое простое обращение:
int God = Utils.GetGodSetting;
04.12.2013
31. При использовании сложных классических WinForms, старайтесь не перегружать код формы. Например, если на форме есть много кнопок, нажатие которых надо обрабатывать, вместо такого кода (особенно если он забойный) … :
public void Btn1_Click(System.Object sender, System.EventArgs e)
{
// Здесь что-то обрабатываем при нажатии на кнопку Btn1
}
public void Btn
2
_Click(System.Object sender, System.EventArgs e)
{
//
Здесь что-то обрабатываем при нажатии на кнопку
Btn
2
}
…
public void BtnN_Click(System.Object sender, System.EventArgs e)
{
//
Здесь что-то обрабатываем при нажатии на кнопку
BtnN
}
… можно создать класс ну скажем clsClickBtn, в который вынести все методы обработки при нажатии на кнопку, а в конструкторе формы разместить сл. код :
Btn1.Click += new EventHandler(clsClickBtn.Btn1_Click);
Btn2.Click += new EventHandler(clsClickBtn.Btn2_Click);
…
BtnN.Click += new EventHandler(clsClickBtn.BtnN_Click);
Код формы в этом случае может сильно ‘похудеть’.
04.12.2013, г. Юрьевец
32. Ещё один подход к обозначенной в п. 31 проблеме может быть следующий.
Сначала создаём структуру ну допустим для обработки нажатий на гиперссылку LinkLabel:
struct struLL
{
public LinkLabel l;
public LinkLabelLinkClickedEventHandler h;
public struLL( LinkLabel _l, LinkLabelLinkClickedEventHandler _h)
{
this.l = _l;
this.h = _h;
}
}
Далее создаём список из обозначенной выше структуры, что-то вроде такого:
private List GetLLList
{
get
{
List opList = new List();
opList.Add(new struLL(lL_A, clsLLblClick.MethodA));
opList.Add(new struLL(lL_B, clsLLblClick.MethodB));
/* …. */
opList.Add(new struLL(lL_Z, clsLLblClick.MethodZ));
return opList;
}
}
Для инициализации методов обработки при нажатии на гиперссылки (в случае нашего примера) осталось только в конструкторе формы прокрутить такой цикл:
foreach (struLL ll in GetLLList)
ll.l.LinkClicked += ll.h;
31.12.2013
33. Каким образом можно проитерировать управляющие элементы (контролы в просторечии) на форме? Один из подходов описан в Совете 26. Но существует ещё одно решение, пожалуй даже более изящное и простое. Заключается оно в том, что нужные контролы просто помещаем на форме в какой-либо контейнер, типа Panel. В этом случае в конструктор формы помещаем такой простой код (как пример для Кнопок — объект Button) для обработки нажатий :
// Цикл по кнопкам в панели 1…
foreach (Button btn in panel1.Controls)
btn.Click +=new EventHandler(btnClik);
28.03.2014
34. При работе со справочниками часто требуется вернуть значение кода (ключа) по значению описания ключа. Конечно, можно для решения такой задачки создать структуру с двумя полями. Но гораздо проще воспользоваться одной из уже существующих коллекций — например словарем Dictionary. Тогда указанный подход можно продемонстрировать на сл. примере.
Создаем следующий метод :
public static int ReturnKodTown(string s)
{
Dictionary DicTowns = new Dictionary();
DicTowns.Add(1, «Москва»);
DicTowns.Add(2, «Санкт-Петербург»);
DicTowns.Add(3, «Казань»);
DicTowns.Add(4, «Новосибирск»);
DicTowns.Add(5, «Краснодар»);
return DicTowns.First(a => a.Value == s).Key;
}
Теперь узнать код города для нашего примера очень легко:
string gorod = »
Новосибирск
«;
int kod = ReturnKodTown (gorod);
09.08.2014
35. При использовании параметризованных SQL-запросов предпочтительнее пользоваться более современным методом .AddWithValue вместо .Add. Указывать тип поля при таком подходе не обязательно, нужно только указать параметр и его значение:
var myCMD = new SqlCommand(strInsSvod, GlobalVar.conn)
var pars = myCMD.Parameters;
pars.Clear();
//
Используем метод
AddWithValue pars.AddWithValue(«@myPar», myVal);
28.09.2014
36. В развитии темы использования более рациональных подходов создания параметризованных запросов (Совет 35). У коллекции параметров Parameters объекта Command есть ещё один полезный метод, позволяющий загрузить пaраметры в запрос массивом. Называется он . AddRange :
// Готовим массив параметров …
private static SqlParameters[] GetMyPars
{
get
{
SqlParameter[] sqlPar = new SqlParameter[] { new SqlParameter(«@par1», myVal1)),
new SqlParameter(«@par2», myVal2)),
…
new SqlParameter(«@parN», myValN))
}
return sqlPar;
}
// Использование метода .AddRange
using (var cmd = new SqlCommand(s, GlobalVar.conn))
{
var pc = cmd.Parameters;
pc.Clear();
pc.AddRange(GetMyPars);
cmd.ExecuteNonQuery();
}
28.09.2014
37. При инициализации коллекций типа List вместо такого кода:
List MyList = new List();
MyList. Add(«один») ;
MyList.Add(«два»);
MyList.Add(«три»);
…
MyList.Add(«девять»);
… можно использовать более короткую эквивалентную запись:
var MyList = new List
{ «один», «два», «три»,
…
«девять»
}
07.01. 2015
38. При работе с коллекциями иногда хотелось бы не только проитерировать их в одном операторе, но и совершить какую-то обработку. В качестве примера , предположим, что есть массив :
var myInt = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
… и для значений массива меньше или равно 5, нужно умножить на 2, а для более 5 умножить на 3.
Здесь на помощь может придти делегат Func и блочный лямбда-оператор. Что-то вроде этого (понятное дело, блочный лямбда-оператор может быть много сложнее и состоять не из одной строки, как в случае нашего простенького примера):
Func myFunc = (z, y) => {
return (z myFunc(a, 5)).ToArray();
10.01. 2015 , г. Обнинск
40. Назначить свой обработчик событий, скажем, для ввода данных в TextBox можно еще и с использование лямбда-оператора сл. образом (метод MyObrabKeyPress) :
textBox1.KeyPress += (o, e) => MyObrabKeyPress( o, e);
Тогда, даже можно создать свой метод для обработки нажатий в нескольких контролах, что-то вроде такого:
void ObrabTxtKeyPress()
{
textBox1.KeyPress += (o, e) => MyObrabKeyPress( o, e);
textBox2.KeyPress += (o, e) => MyObrabKeyPress( o, e);
textBox3.KeyPress += (o, e) => MyObrabKeyPress( o, e);
…
textBoxN.KeyPress += (o, e) => MyObrabKeyPress( o, e);
}
Затем, такой метод лучше всего поместить в конструктор формы, на которой расположены наши контролы (TextBox’ы для случая нашего примера) :
public frmMain()
{
InitializeComponent();
…
ObrabTxtKeyPress();
}
09.11. 2015
41. Тем, кто создает приложения для работы с базами данных, случается иметь дело с весьма ‘забойными’ SQL-запросами, которые могут занять десятки строчек кода. Но хранить такие запросы в тексте программы, несмотря на определенное удобство для разработчика (код запроса виден прямо в теле программы) не всегда изящно по причине необходимости ‘сцепки’ строчек в запросе. И здесь возможно два варианта решения задачи хранения ‘тяжелых’ запросов. Первый заключается в перемещении запроса непосредственно в базу данных в виде хранимой процедуры (Store Procedure). Второй путь связан с перемещением скрипта в строковую переменную в Настройки (Setting, см. п.30)
09.11. 2015
42. В продолжении темы п.41 . В код программы на C# ‘запилить’ длинный SQL-запрос можно используя символ литерала ‘@’. В этом случае отпадает необходимость в конкатенации строк. Выглядит такая конструкция может приблизительно сл. образом :
string mySql = @»Первая длинная строка запроса
Вторая ну очень длинная строка запроса
Третья длинная строка запроса
…
Последняя строка ну очень длинного запроса»;
29.05. 2016
Simashkov.2010-2016

Жмём кнопку Extract и видим следующий результат:

Таак … Слой точек создали. Теперь нужно вычислить координаты X/Y для каждой точки. Это можно сделать с помощью функций Centroid X/Y. Идём меню Запрос>SQL-запрос и заполняем реквизиты формы приблизительно сл. образом:

Тут существует одна небольшая тонкость. Дело в том, что по умолчанию координаты карты будут вычисляться в географической системе координат Долгота/Широта (градусы). Если вы работаете в плановой системе координат, то необходимо будет поменять географическую систему на плановую. Для этого идём меню Настройки>Режимы>Окно карты> вкладка Проекция:
На рисунке выше жмём на кнопку Проекция таблицы и выбираем систему координат План-схема:

Теперь, если после этих манипуляций нажать на кнопку OK (на форме SQL-запроса), то получим следующую таблицу со значениями координат точек и параметра Z (pH в нашем случае):

Осталось только «вытолкнуть» эти данные в текстовый файл. Для этого идём Таблица>Экспорт и выбираем тип файла ASCII (.txt):

Жмём на кнопку Сохранить и выбираем символ для разделения значений координат:
![]() |
Здесь в качестве разделителя мы выбрали запятую. |
Ну вот, задача, собственно, решена. Теперь, если открыть полученный файл любым текстовым редактором, можно увидеть приблизительно следующее его содержание:

Сгенерированный таким образом файл можно передавать на обработку в любое стороннее приложение.
Удачи!
© Simashkov.2011
01.04.2011 г.
Как создать простое интерактивное ГИС Web-приложение с использованием движка Google, можно посмотреть
© Simashkov.2013
12.04.2013 г.
Каталог Программ и попадаем в форму загрузки встроенных утилит MapInfo. Далее ставим флажок напротив утилиты Извлечь координаты (Coordinate Extractor в англ. версии):

В меню Программы появляется новый пункт — Записать координаты объекта. Жмём на него :

Видим такую форму утилиты загрузки координат:

На рисунке выше, если заранее не подготовили колонки в таблице для записи координат, жмём кнопку Создать новые колонки для координат. На следующей форме задаём названия колонок:
После отработки указанной утилиты наш новый список может выглядеть приблизительно следующим образом (обведено красным в заголовках списка):

Задача решена !
Способ 2.
С использованием
SQL-
запроса
Для выполнения поставленного задания по извлечению координат идём в меню Запрос>SQL-запрос и далее заполняем реквизиты запроса приблизительно так, как указано на рисунке ниже.
Текст запроса : Name, CentroidX(obj) «Долгота», CentroidY(obj) «Широта» :

Небольшой комментарий к рисунку выше. Для вычисления координат используются географические функции CentroidX/Y(obj) и в кавычках задаём имена полей, в которые будем заносить данные.
Результат будет полностью аналогичен тому, что мы получили по первому способу.
Как решить аналогичную задачу по определению координат в ArcGIS — смотрите на нашем сайте по этой ссылке
О том, как создать в MapInfo каталог координат — смотрите тут
©Simashkov.2011.
02.10.2011 г.

Выбрав указанный пункт и пройдя стандартные формы мастера, видим сл. окно редактирования легенды карты ( как пример):

Очевидно, что редактор легенды в версии MapInfo 11.5 существенно переработан разработчиками и в нём появились новые возможности. Начнём, пожалуй, с создания направляющих для выравнивания. Сразу необходимо заметить, что они доступны при включённой опции по правой кнопке мыши в контекстном меню Enable Guidelines :
Теперь можно добавить, скажем, вертикальную направляющую для выравнивания пунктов легенды по левому или правому краю:
Чтобы прижать нужный пункт легенды, достаточно выделить его и нажать соответствующую кнопку:

Ещё одним новшеством в редакторе легенд является возможность нанесения выравнивающей сетки:

Размер шага сетки устанавливается соответствующим ползунком. Далее. Если выставить флажок Snap, то при перемещении пунктов легенды, они будут выравниваться (‘прилипать’) по направляющим сетки:

Чтобы отредактировать подписи пункта легенды, достаточно ( как в предыдущих версиях) дважды щёлкнуть по нему:

Созданный макет карты с оформленной таким образом легендой может выглядеть приблизительно так:

В общем, внесённые в редактор легенды новые возможности ( в версии MapInfo 11.5) представляются весьма полезными и значительно облегчат труд создателей макетов карт.
Как создать легенду в ГИС MapInfo можно посмотреть ещё здесь
© Simashkov.2012
01.07.2012 г.

Если воспользоваться последним способом, то загрузиться панель инструментов Geostatistical Analyst, имеющая следующий вид:

Сейчас попробуем освоить, пожалуй, один из самых замечательных (и мощных) инструментов для неискушённого в вопросах пространственного анализа пользователя в ArcGIS — помощник GeoStatistical Wizard. Он, как действительно настоящий волшебник (одно из значений перевода английского слова Wizard), проведёт вас за руку через все препятствия для выполнения задачи по интерполяции данных. Итак, смело в путь.
Материалы этого учебного примера можно Просмотреть по этой ссылке
Жмём на пункт меню GeoStatistical Wizard и попадаем на форму выбора метода интерполяции — по умолчанию выбираем один из самых распространённых методов — по Кригингу . Вообще, если говорить о теории, методы интерполяции делятся на две категории — детерминированные и геостатистические. Метод Кригинга относится к последним :

… жмём кнопку Next :

Для первого раза оставляем всё как есть и продолжаем движение ( Шаг 3) — появляется форма с отображение вариограмм (пока обсуждение, что такое вариограмма и для чего она нужна оставим за кадром — это тема отдельного разговора):

Движемся дальше и попадаем в окно настроек метода поиска ближайших (Neighborhood) точек (этот момент тоже важен для интерполяции пространственного распределения):
бо
Таак … Постепенно приближаемся к финишу. В очередной раз жмём кнопку Next:
Дальше начинается совсем тёмный лес 🙂 .
Видим статистические результаты оценки нашей интерполяции:

Не беспокойтесь, если на форме выше пока не всё понятно (строго говоря, чтобы разобраться во всей информации на этой форме, надо иметь весьма солидную подготовку в области мат. статистики и методов интерполяции). Но пока смело идём дальше …
Вот он, наш долгожданный Финиш — любуемся на карту интерполированного растра, созданного на наших учебных данных методом Kriging (Кригинга). Для первого раза везде мы выбирали параметры по умолчанию:

Один интересный момент. Для интерполяции можно выбирать не все объекты из набора данных. Выделив в атрибутивной таблице только нужные нам точки ( в данном случае), можно получить приблизительно такой результат:

Продолжаем. Если в качестве примера, выбрать на форме шага 2 опцию поиска ближайших точек Smooth :
… то увидим такой результат (поверхность Kriging_2):

И в заключении, в качестве примера, приведём картинку интерполяции по ещё одному популярному методу — Обратных взвешенных расстояний (Idw):

В общем, как видите, Geostatistical Wizard — это ваш настоящий помощник на первых шагах при освоении методов пространственного анализа и интерполяции данных в ArcGIS. Стоит присмотреться и изучить его повнимательнее …
Ещё об интерполяции в ArcGIS можно посмотреть в этой статье и здесь
Более подробно об использовании ArcGIS Geostatistical Analyst http://esri-cis.ru/support/articles_by_working_with_software/10286/#1
По умолчанию, в штатной поставке уже приведены URL несколько доступных WMTS-серверов :
Попробуем для начала воспользоваться австралийским сервисом :
Подключаемся к нему и обнаруживаем такую карту Австралии:
Весьма показательным в плане предоставления пользователям доступа к ортофото-снимков высокого разрешения является сервис Чешской Республики :
В качестве иллюстрации того, что можно загрузить в виде подложки с вышеуказанного чешского сервера, приведем такую картинку :
Из примеров использования WMTS-спецификации в отечественных Web-сервисах геоданных можно привести ГИС Красноярского края URL http://map.24bpd.ru/geowebcache/service/wmts? :
Необходимо заметить, что, как пишут в Инете, многие современные сервисы геоданных типа Google Maps, Яндекс.Карты и пр. работают именно по спецификации WMTS. Так что новая функциональность явно не будет лишней с позиции предоставления пользователям возможности быстрее загружать онлайновые подложки для своих карты.
О том, как можно подключиться к онлайновым картам по спецификации WMS, смотрите здесь
© Simashkov.2018
02.05.2018 г.