Компьютерный помощник

Нехитрые советы для пользователей ПК

     < На Главную

Технологическая инструкция по оцифровке сх/контуров внутрихозов масштаба 1: 10 000 c использованием космоснимков Landsat

 I. Определения

 1. Контур сельскохозяйственных угодий (сх/контур)  – часть земель, используемых или предназначенных для производства сельскохозяйственных культур, сенокошения и выпаса сельскохозяйственных животных  (пашня, сенокосы, пастбища, залежь, многолетние насаждения) и ограниченная естественными природными или искусственными объектами антропогенного характера (дорогами, строениями, лесополосами, оврагами лесными массивами и водными объектами).

2. Сельскохозяйственный полигон (полигон) – часть контура сельскохозяйственных угодий, занятая однородными сельскохозяйственными культурами (имеет однородную спектральную плотность на космоснимке). 

3. Внутрихоз – землеустроительный план сельскохозяйственного предприятия, оформленный в виде землеустроительного плана масштаба 1 : 10 000 или картограммы масштаба 1: 25 000.

 II. Инструкция

 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:

fig13-2944729

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

fig14-9004695

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

fig15-1219264

© Simashkov.2012

07.04.2012 г.

Назад

Калькулятор Дальностей>Выполнить :

pdist4-8176135

… и далее задаём опции приблизительно так, как указано на рисунке ниже:

analyzdalnostey-5493055

Небольшой комментарий. По логике задачи будем промерять расстояния от нас. пунктов (слой Klg_RayCenter) до аэродромов (Airports). Поскольку в нашем примере 3 объекта, до которых нужно узнать расстояния, то в поле Количество дальностей и указываем именно такое значение.

Для генерации списка дальностей жмём на кнопку Вычислить, и в случае необходимости сохранить результаты , естественно кликаем по соответствующей кнопке. Результат измерений отобразиться в списке слева в колонке Дальность.

Теперь нам нужно будем обработать полученные результаты — сгруппировать (просуммировать) расстояние до каждого аэродрома. Проще всего это будет сделать с помощью соотв. запроса по меню Запрос>SQL — запрос и набрать его так, как показано на сл. картинке (самое важное здесь — указать группировку по полю Цель для нашего примера):

sqlzapros-4081324

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

calcdistance-5644949

Не надо быть большим специалистом по выбору локализаций объектов гражданской авиации, чтобы понять, что аэропорт Грабцево (в случае нашего примера) по критерию минимальной удаленности от основных нас. пунктов региона  выглядит наиболее предпочтительно.

Как решить аналогичную задачу в ArcGIS, можно посмотреть здесь

© Simashkov.2014

07.12.2014 г.

Назад

0)

  {

       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

Назад

 Запустить программу MapBasic). В  меню появляется пункт Tools. Идём далее p2p>Polyline to points и на следующей форме выбираем параметр Z, который желаем сохранить в таблице. Пусть в нашем случае это будет значение pH(кислотность почв, для тех, кто не знает 🙂 :

screen2-5179479

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

screen4-5741774

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

screen11-7106370

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

На рисунке выше жмём на кнопку Проекция таблицы и выбираем  систему координат План-схема:

screen6-3422200

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

screen7-7196413

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

screen8-4688269

Жмём на кнопку Сохранить и выбираем символ для разделения значений координат:

screen9-5384615 Здесь в качестве разделителя мы выбрали запятую.

Ну вот, задача, собственно, решена. Теперь, если открыть полученный файл любым текстовым редактором, можно увидеть приблизительно следующее его содержание:

screen10-5135527

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

Удачи!

© Simashkov.2011

01.04.2011 г.

Назад

Сохранить окно как …) в какой-либо растровый файл. Затем просто вставляем этот файл в нашу html-страничку.

Как создать простое интерактивное ГИС Web-приложение с использованием движка Google, можно посмотреть

здесь

© Simashkov.2013

12.04.2013 г.

Назад

 Каталог Программ  и попадаем в форму загрузки встроенных утилит MapInfo. Далее ставим флажок напротив утилиты Извлечь координаты (Coordinate Extractor в англ. версии):

fig6-1712828

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

fig7-4103425

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

fig8-1844895

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

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

fig10-5863966

Задача решена !

Способ 2.

С использованием

SQL-

запроса

Для выполнения поставленного задания по извлечению координат идём в меню Запрос>SQL-запрос и далее заполняем реквизиты запроса приблизительно так, как указано на  рисунке ниже.

Текст запроса :   Name, CentroidX(obj) «Долгота»,  CentroidY(obj) «Широта» :

fig11-8890340

Небольшой комментарий к рисунку выше. Для вычисления координат используются географические функции CentroidX/Y(obj) и в кавычках задаём имена  полей, в которые будем заносить данные.

Результат будет полностью аналогичен тому, что мы получили по первому способу.

Как решить аналогичную задачу по определению координат в ArcGIS — смотрите на нашем сайте по этой ссылке

О том, как создать в MapInfo каталог координат — смотрите тут

©Simashkov.2011.

02.10.2011 г.

Назад

Создать Легенду):

fig2-5334228

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

fig3-4504069

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

Теперь можно добавить, скажем, вертикальную направляющую для выравнивания пунктов легенды по левому или правому краю:

Чтобы прижать нужный пункт легенды, достаточно выделить его и нажать соответствующую кнопку:

fig9-1358439

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

fig8-1980442

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

fig10-6888954

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

fig7-5850579

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

fig11-4623969

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

Как создать легенду в ГИС MapInfo можно посмотреть ещё здесь

© Simashkov.2012

01.07.2012 г.

Назад

Toolbars:

fig1-9502115

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

fig16-4453352

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

Материалы этого учебного примера можно Просмотреть по этой  ссылке

Жмём на пункт меню GeoStatistical Wizard и попадаем на форму выбора метода интерполяции — по умолчанию выбираем один из самых распространённых методов  — по Кригингу . Вообще, если говорить о теории, методы интерполяции делятся на две категории — детерминированные и геостатистические. Метод Кригинга относится к последним :

fig3-4234770

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

fig4-7566207

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

fig5-1030482

Движемся дальше и попадаем в окно настроек метода  поиска ближайших (Neighborhood) точек (этот момент тоже важен для интерполяции пространственного распределения):

fig6-7699431бо

Таак … Постепенно приближаемся к финишу. В очередной раз жмём кнопку Next:

Дальше  начинается совсем тёмный лес 🙂 .

Видим статистические результаты оценки нашей интерполяции:

fig7-5499254

Не беспокойтесь,  если на форме выше пока не всё понятно (строго говоря, чтобы разобраться во всей информации на этой форме, надо иметь весьма солидную подготовку в области мат. статистики и методов интерполяции). Но пока смело идём дальше …

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

fig14-3639364

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

fig9-8362598

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

… то увидим такой результат (поверхность Kriging_2):

fig15-8623243

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

fig12-1156947

В общем, как видите, Geostatistical Wizard — это ваш настоящий помощник  на первых шагах при освоении методов пространственного анализа и интерполяции данных в ArcGIS. Стоит присмотреться и изучить его  повнимательнее …

Ещё об интерполяции в ArcGIS можно посмотреть в этой статье  и здесь

Более подробно об использовании ArcGIS Geostatistical Analyst http://esri-cis.ru/support/articles_by_working_with_software/10286/#1

Mapping WMTS :

По умолчанию, в штатной поставке уже приведены URL несколько доступных  WMTS-серверов :

Попробуем для начала воспользоваться австралийским сервисом  :

Подключаемся к нему и обнаруживаем такую карту Австралии:

Весьма показательным в плане предоставления пользователям доступа к ортофото-снимков высокого разрешения является сервис Чешской Республики :

В качестве иллюстрации того, что можно загрузить в виде подложки с вышеуказанного чешского сервера, приведем такую картинку  :

Из примеров использования WMTS-спецификации в отечественных Web-сервисах геоданных можно привести   ГИС Красноярского края  URL  http://map.24bpd.ru/geowebcache/service/wmts? :

Необходимо заметить, что, как пишут в Инете, многие современные сервисы геоданных типа Google Maps, Яндекс.Карты и пр. работают именно по спецификации WMTS. Так что новая функциональность явно не будет лишней с позиции предоставления пользователям  возможности быстрее загружать онлайновые подложки для своих карты.

О том, как можно подключиться к онлайновым картам по спецификации WMS, смотрите здесь

© Simashkov.2018

02.05.2018 г.

Назад