УДК 004.9: 681.3 3 страница

10. Постройте с использованием векторной топологической модели простейшую БД, содержащую описание расположения семи векторных объектов.

11. Схематично проиллюстрируйте метод цифрового описания пространственного объекта на основе нерегулярной триангуляционной сети.

12. Поясните назначение и принцип организации растровых моделей данных. Для чего используются нерегулярная и регулярная сети точек?

13. Каким образом осуществляется построение цифровой карты в виде множества слоев? Какие преимущества пользователям предоставляет работа со слоями?

14. Перечислите основные форматы данных ГИС. Постройте классификацию форматов по нескольким основаниям, приведите примеры.

15. Поясните назначение, функции, состав и преимущества БД ГИС.

16. Что такое модель данных в БД ГИС? Поясните принцип организации реляционной модели БД в ГИС.


3. ТЕХНОЛОГИИ ВВОДА И ХРАНЕНИЯ ДАННЫХ

3.1. Способы ввода данных

В соответствии с используемыми техническими средствами различают два способа ввода данных: дигитализацию и векторизацию. Для ручного ввода пространственных данных применяется дигитайзер. Он состоит из планшета (столика) с электронной сеткой, к которому присоединено устройство называемое курсором. Курсор представляет собой подобие графического манипулятора – мыши, имеет визир, нанесенный на прозрачную пластинку, с помощью которого оператор выполняет точное наведение на отдельные элементы карты. На курсоре помещены кнопки, которые позволяют фиксировать начало и конец линии или границы области, число кнопок зависит от уровня сложности дигитайзера. Дигитайзеры бывают разных форматов и обеспечивают разрешение 0,03 мм с общей точностью 0,08 мм на расстоянии 1,5 м. Существуют автоматизированные дигитайзеры, обеспечивающие автоматическое отслеживание линий.

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

Процесс цифрования растрового изображения на экране компьютера называют векторизацией. Существует три способа векторизации: ручной, интерактивный и автоматический. При ручной векторизации оператор обводит мышью на изображении каждый объект, при интерактивной - часть операций производится автоматически. Так, например, при векторизации горизонталей достаточно задать начальную точку и направление отслеживания линий, далее векторизатор сам отследит эту линию до тех пор, пока на его пути не встретятся неопределенные ситуации, типа разрыва линии. Возможности интерактивной векторизации прямо связаны с качеством исходного материала и сложностью карты. Автоматическая векторизация предполагает непосредственный перевод из растрового формата в векторный с помощью специальных программ, с последующим редактированием. Оно необходимо, поскольку даже самая изощренная программа может неверно распознать объект, принять например, символ за группу точек, и т.п.

3.2. Преобразование исходных данных

Отсканированные исходные карты создавались в определенной картографической проекции и системе координат. При оцифровке эта сложная проекция сводиться в набор пространственных координат. Поэтому необходимо преобразовать карту к ее исходной проекции. Для этого в ГИС вводятся сведения об используемой проекции (обычно ГИС позволяет работать с большим числом проекций) и осуществляется ряд преобразований. Три основных из них, которые часто выполняются одновременно, это перенос, поворот и масштабирование.

Перенос – это просто перемещение всего графического объекта в другое место на координатной плоскости. Он выполняется добавлением определенных величин к координатам Х и У объекта:

Масштабирование тоже очень полезно, так как часто сканируются карты разных масштабов, для этого используют соотношение:

Поворотвыполняется с использованием тригонометрических функций:

Все необходимые преобразования могут быть выполнены и использованием этих трех основных графических операций по координатам опорных точек.

3.3. Ввод данных дистанционного зондирования

В ГИС используют не первичные материалы дистанционного зондирования (ДЗ), получаемые во время съемки, а производные, формируемые в результате их обработки. Данные со спутников подвергаются предварительной цифровой обработке для устранения радиометрических и геометрических искажений, влияния атмосферы и т.д. Для улучшения визуального качества исходных изображений могут применяться процедуры для изменения яркости и контрастности, фильтрации для устранения шумов или подчеркивания контуров и мелких деталей. При использовании аэрофотоснимков следует обращать внимание на искажения, вызываемые углами наклонов снимков и рельефом местности, которые могут быть устранены в процессе трасформирования или ортофототрансформирования. [4]

3.4. ГИС-специфическое хранение геоданных

Широко распространенным форматом файлов для представления пространственных данных является формат .shp (shapefile), разработанный организацией ESRI (Environmental Systems Research Institute) в 1997-1998 годах. Многие СУБД, в том числе и Open Source – решения, имеют утилиты для импорта данных из .shp - формата и экспорта данных в этот формат.

Фактически shape-файл является набором минимум из трех файлов:

- .shp для хранения геометрических данных;

- .dbf атрибуты в формате dBASE;

- .shx служит в качестве индекса для согласования геометрических данных и атрибутов.

Другим распространенным форматом представления пространственных данных является GML (Geography Markup Language), разработанный OGC. Фактически он является расширением XML.

Преимуществами хранения данных в файлах являются их простота и быстрый доступ к данным.

При этом однако, могу возникать проблемы при распределенном доступе, а также связанные со специфическими ограничениями формата (например фиксированная длина строки).

3.4.1. Гибридное хранение

При гибридном хранении геоданных геометрические данные находятся в файле, а атрибуты – в реляционной БД. Примером ГИС, использующей подобную схему хранения данных, является Bentley Systems (MicroStation Geographics).

Эта схема обеспечивает быстрый доступ к геометрическим данным.

Несмотря на то, что геометрические данные относительно статичны и не часто подвергаются изменениям, существует опасность потери целостности данных из-за раздельного хранения ключей. Также существуют ограничения в многопользовательском режиме.

3.4.2. Хранение геоданных в реляционной БД

Подобную модель используют такие ГИС, как ESRI (ArcGIS), Smallworld (Smallworld GIS), Intergraph (GeoMedia).

 
 

БД предоставляют в этом случае все преимущества работы с данными, включая защиту целостности и защиту данных, а также различные методы опроса и анализа данных. Однако в результате распределения сложных объектов по многим таблицам страдает скорость обработки данных.

3.4.3. Базовые пространственные запросы

ГИС приняты четыре основных типа геометрических данных:

- точка (узлы, вершины);

- линия (незамкнутая);

- контур (замкнутая линия);

- полигон (ареал).

Свойства базовых типов, как и отношения между ними описываются в модели данных.

БГД должна предоставлять методы для работы с базовыми типами и функции для выполнения типичных пространственных операций, как например:

- нахождение пересечения двух площадей;

- определение длины линии.

Пространственные операции могут использоваться непосредственно в SQL-запросе для всех определенных в запросе объектов (в инструкции SELECT) или в условии запроса (в инструкции WHERE), например:

- рассчитать площадь всех федеральных округов;

- определить все области, находящиеся в опрашиваемом федеральном округе.

- пространственным запроcам относятся запросы, в условии которых используются пространственные операторы. Типичными пространстренными запросами являются:

- точечные запросы (англ. Point Query) – определение всех геообъектов, содержащих заданную точку p.

Оконные запросы (англ. Window Query) – определение всех геообъектов, пересекающих заданную прямоугольную область r (т.е. находящихся в области или пересекающих ее край).

Полигонные запросы (англ. Region Query) – определение всех геообъектов, пересекающих заданный полигон pol (т.е. находящихся в полигоне или пересекающих его край).

 

Запросы удаленности (англ. Distance Queries) – определение всех геообъектов, находящихся в пределах заданного расстояния dist от данной точки p. Такие запросы равнозначны полигонным запросам с полигоном в форме окружности радиуса dist.

Запросы ближайшего соседа (англ. Nearest Neighbor Query) – определение ближайших объектов к заданному геообъекту g. Вариантом запроса может быть нахождение k ближайших соседей. [8]

Пространственное соединение (англ. Spatial Join) – операция соединения двух таблиц, содержащая минимум одно пространственное условие (например, найти все пары пересекающихся геообъектов – Intersection Join).

3.4.4. Ограничение реляционной модели данных

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

Например, имеется таблица для хранения линий:

Line={LNr, PNr, x, y},

где LNr номер линии, PNr номер точки, x значение абсциссы, y значение ординаты.

 
 

Запрос для определения полигонов, пересекающих прямоугольник с координатами углов

(4, 4) и (6, 5):

SELECT *

FROM Line WHERE x >= 4

AND y >= 4 AND x <= 6 AND y <= 5;

Запрос находит точки полигонов и соответственно полигоны. Теперь полигоны в таблице сохранены более грубо:

 
 

Такой же запрос, как и прежде, не выдаст ни одной точки, хотя отчетливо видно, что прямоугольник пересекается двумя полигонами.

3.5. Объектно-ориентированные БД

Моделирование данных в объектно-ориентированных БД (ООБД) базируется на понятии объекта и является более близкой к сущностям реального мира.

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

Объекты могут находиться в определенных отношениях друг к другу. Объект может состоять из других объектов, т.е непосредственно включать в себя другие объекты или же ссылаться на них.

Объекты взаимодействуют между собой с помощью сообщений. Принимая сообщение, объект выполняет соответствующее действие (метод).

Объекты обладают свойствами инкапсуляции, полиморфизма и наследования.

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

Различные объекты могут по разному реагировать на одинаковые внешние события в зависимости от того, как реализованы их методы (полиморфизм).

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

Посредством механизма наследования между классами возможно определение новых классов, которые наследуют структуру и методы своих предков, добавляя к ним черты, отражающие их собственную индивидуальность.

Одним из методов создания объектно-ориентированных БД является встраивание в объектно-ориентированный язык средств для работы с базами данных.

В объектно-ориентированных БД, в отличие от реляционных, хранятся не записи, а объекты.

К достоинствам объектно-ориентированных БД можно отнести широкие возможности моделирования предметной области, выразительный язык запросов и повышенную производительность. Эти модели обычно применяются для сложных предметных областей, для моделирования которых не хватает функциональности реляционной модели. Модульное программирование значительно упрощает расширение и сопровождение продукта. Уже разработанные компоненты можно повторно использовать и довольно гибко подгонять под новые требования посредством механизма наследования.

Среди недостатков объектно-ориентированной модели следует отметить отсутствие универсальной модели, недостаток опыта создания и эксплуатации объектно-ориентированных БД, сложность использования и недостаточность средств защиты данных (по причине отсутствия развитых средств манипуляции данными).

Примером объектно-ориентированных БД является FastObjects от Intersystems – постреляционная БД с поддержкой SQL.

3.6. Хранение объектов в JAVA (сериализация)

Простейшим стандартным средством JAVA для сохранения состояний объектов в файл (последовательности битов) является механизм сериализации. Механизм сериализации не являетсяреализацией СУБД.

Механизм сериализации основан на интерфейсе java.io.Serializable.

При сохранении объектов применяется класс ObjectOutputStream, при восстановлении - ObjectInputStream.

Пример:

Описание класса MyData, сохранение и восстановление объектов которого необходимо обеспечить:

import java.io.*;

public class MyData implements Serializable

{String name; String vorname; int id;

public MyData(int id, String v, String n)

{this.id = id; this.name = n; this.vorname = v;}

public String toString()

{return name + ", " + vorname + " (" + id + ")";}}

Реализация сохранения объектов класса MyData:

static String name = "myData.ser"; static void schreiben()

{FileOutputStream file = null; try

{file = new FileOutputStream(name);

ObjectOutputStream out = new ObjectOutputStream(file); MyData data = new MyData(1, "Rudi", "Ratlos"); out.writeObject(data);

out.close(); file.close();}

catch (FileNotFoundException ex1)

{ex1.printStackTrace();}

catch (IOException ex2)

{ex2.printStackTrace();}}

 

Реализация восстановления объектов класса MyData:

static String name = "myData.ser"; static void lesen()

{FileInputStream file = null; try

{file = new FileInputStream(name);ObjectInputStream in = new ObjectInputStream(file); MyData data = (MyData) in.readObject(); System.out.println(data);

in.close(); file.close();}

catch (FileNotFoundException ex1)

{ex1.printStackTrace();}

catch (IOException ex2)

{ex2.printStackTrace();}

catch (ClassNotFoundException ex3)

{ex3.printStackTrace();}}

Сам по себе интерфейс Serializable не имеет никаких методов и служит лишь для указания того, что объекты будут сохраняться и восстанавливаться посредством описанных возможностей [10].

Данный пример демонстрирует лишь общую схему описания и использования сериализации. [17]

3.7. ООБД DB4OBJECTS

DB4O (DB4OBJECTS) – встраиваемая объектно-ориентированная СУБД для JAVA и .NET-языков (C++, C#, Visual Basic); фактически это объектно-ориентированная библиотека для организации БД.

Для некоммерческого использования DB4O доступна под лицензией GPL. Возможно также использование в серверном режиме.

Ключевыми преимуществами DB4O являются быстрота работы, компактность, простота и возможность сохранять JAVA или .NET объекты в исходном виде. Добавление одной библиотеки в проект позволяет получить доступ к DB4O API для работы с базой.

В DB4O БД рассматривается как ObjectContainer. ObjectContainer ассоциируется с определенным файлом на диске. Получение доступа к файлу происходит открытием

ObjectContainer: ObjectContainer db = Db4o.openFile(<filename>).

После завершения операций с БД, вызывается db.close().

Пример:

package testobjectdb;

import com.db4o.*; import javax.swing.*;

public class MyMain

{static String

dbName = "c:\\user\\myObjectDatabase.yap"; static ObjectContainer db;

static void erzeugeDaten() //Внесение данных в БД

{db.set(new MyData(1, "Holger", "Baumann")); db.set(new MyData(2, "Rudi","Testmann")); db.set(new MyData(3, "Harry", "Hirsch")); db.set(new MyData(4, "Rudi","Ratlos"));}

static void sucheDaten() //Поиск данных

{MyData query = new MyData();

query.vorname = "Rudi"; ObjectSet set = db.get(query); while (set.hasNext())

{System.out.println(set.next());}}

static void lцscheDaten() //Удаление данных

{MyData query = new MyData(); query.vorname = "Rudi"; ObjectSet set = db.get(query); while (set.hasNext())

{MyData d = (MyData) set.next();

if (JOptionPane.showConfirmDialog(null, "Datensatz <" + d + "> удалить?") == JOptionPane.OK_OPTION)

{db.delete(d);}}}

public static void main(String[] args)

{db=Db4o.openFile(dbName); // Открытие или создание БД

erzeugeDaten();

sucheDaten();

loscheDaten();

db.close();

System.exit(0);}}

3.8. Объектно-реляционные БД

Объектно-реляционная модель данных является расширением возможностей реляционных БД путем применения в концепции понятия объекта. Это расширение достигается использованием таких объектно-ориентированных компонентов, как пользовательские типы данных, инкапсуляция, полиморфизм, наследование, переопределение методов и т.п.

Одновременно с этим приходится отказываться от требований к нормализации, – особенно от 1NF (атомарность данных).

Ведущие фирмы-производители БД, в числе которых Oracle (с версии 8) и IBM (Informix), расширили возможности своих продуктов до объектно-реляционной СУБД. Среди Open Source – решений следует отметить PostrgreSQL. К сожалению, модели, поддерживаемые различными производителями БД, существенно отличаются по своим функциональным характеристикам. Попытки совместить средства манипуляции данными реляционной модели и способы описания внешнего мира объектно-ориентированной модели получили развитие в языке SQL: 1999 (SQL3). В большинстве реализаций объектно-реляционной модели объектами признаются агрегат или таблица (отношение), которая может входить в состав другой таблицы. Методы обработки данных представлены в виде хранимых процедур и триггеров, которые являются процедурными объектами базы данных и связаны с таблицами. [21]

3.9. Программирование взаимодействия с БД – JDBC и ODBC

JDBC (Java Database Connectivity)– это прикладной программный интерфейс JAVA для взаимодействия с различными СУБД. Он состоит из множества классов и интерфейсов, написанных на языке JAVA.

Стандартный программный интерфейс позволяет едино использовать функции разных СУБД. Разработчику нет необходимости изучать специфику работы с определенной БД. К любой БД можно подсоединиться через легко описываемый URL. Реализация протокола передачи данных с БД известна только драйверу. В случае перехода на другую БД код программы не меняется. Если JDBC-драйвер написан целиком на языке JAVA, то приложение, использующее его, обладает высокой переносимостью.

В настоящее время ODBC (Open DataBase Connectivity) является наиболее популярным при разработке приложений для доступа к БД. Этот интерфейс "понимают" почти все СУБД. Однако ODBC использует интерфейс, наиболее родной для языка C и не совсем подходящий для JAVA. ODBC сложнее для изучения. Он перемешивает в себе одновременно и простые, и сложные возможности и требует сложных программных решений даже для выполнения простейших запросов. При использовании ODBC необходимо на каждую клиентскую машину ставить ODBC-драйвер.

3.10. Типы JDBC

По способу реализации драйверы JDBC подразделяются на 4 типа:

- Type 1: JDBC-ODBC Bridge Driver

- Type 2: Native- API Java Driver

- Type 3: Network-Protoсol All- Java Driver

- Type 4: Native Protocol All-Java Driver

К первому типу относятся драйверы реализованные поверх ODBC драйверов. Все вызовы JDBC транслируются в вызовы ODBC, дальнейшую обработку вызова ведет ODBC. Преимуществом драйверов этого типа является возможность доступа Java приложений к источникам данных, доступным с помощью ODBC; недостатки такого драйвера: низкая скорость работы, трудности конфигурирования и отсутствие поддержки всех возможностей JDBC. [19]

Ко второму типу относятся драйверы, использующие программные части, написанные на других языках. Обычно в этом случае для доступа к данным используются библиотеки, разработанные производителем БД. Такие драйверы как правило очень быстрые, но требуют установки специального программного обеспечения на клиентской машине.

Третий типдрайверов полностью реализуется наJava,но при этом вызовыJDBCтранслируются в сетевой протокол, который далее транслируется в специфичный протокол базы данных. Этот драйвер схож с драйверами JDBC-ODBC, отличие в том, что он полностью реализован на Java, за счет чего отсутствует необходимость в установке клиентского ПО.

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

Порядок работы с JDBC:

- Загрузить JDBC-драйвера;

- Установить соединение с СУБД;

- Создать SQL-запрос;

- Выполнить SQL-запрос;

- Получить результаты запроса;

- Закрыть соединение с БД;

- Установление и закрытие соединения с БД.

Для успешной загрузки драйвера необходимо удостовериться, чтобы файл с библиотекой содержащей указанный класс драйвера находился в переменной окружения CLASSPATH.

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

Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );

Class.forName( "oracle.jdbc.driver.OracleDriver" );

Соединение с БД производится единственным способом — вызовом метода:

Connection con = DriverManager.getConnection(url, user, password);

URL служит для идентификации источника данных драйвером JDBC. В самом общем виде синтаксис URL драйвера следующий:

jdbc:<subprotocol>:<subname>

Первая часть URL (слово jdbc), является зарезервированной и обозначает протокол доступа.

<subprotocol> обозначает имя драйвера или название механизма соединения. <subname> обозначает источник данных.

Например для драйвера Oracle:

jdbc:oracle:thin: [<user>/<password>] @<host>:<port>:<sid>

Пример:

final String url = "jdbc:oracle:thin:@vw-s2k04.vw.w2000.hs-anhalt.de:1521:gisdb1";

Connection con = DriverManager.getConnection(url, user, password);

Для окончания сеанса работы используют метод close():

con.close();

В случае, если метод закрытия не вызывался, соединение закроется автоматически с помощью Garbage-коллекций Java, однако определить время закрытия в этом случае не представляется возможным.

3.11. Выполнение SQL-запроса

После получения соединения с БД (интерфейс Connection), необходимо создать SQLStatement–специальныйJAVAобъект для выполненияSQLзапросов:

Statement stmt = con.createStatement();

Для выполнения SQL запроса используется метод executeQuery (query):

String query = "SELECT * FROM Tabellenname;"; ResultSet rs = stmt.executeQuery (query);

Является ли запрос безошибочным, на этом этапе выполнения программы не проверяется.

Метод возвращает объект типа ResultSet. По сути это внутренняя таблица с набором записей и внутренним указателем на текущую запись. По умолчанию указатель ResultSet может двигаться только вперед и его содержимое не может меняться. Для перемещения по ResultSet используется метод next(). Методом getObject() опрашиваются отдельные поля записи. Для доступа к ним можно использовать два альтернативных способа: по имени поля или по его порядковому номеру.

Пример:

while (rs.next())

{System.out.println(rs.getString(1);}

while (rs.next())

{System.out.println(rs.getObject(“Name“));}

Метаданныеописывают структуру БД,результирующего набора или параметров,какнапример:

- текущие соединения;

- режим работы с БД (чтение или запись);

- возможность сохранения и выполнения процедур;

- количество опрашиваемых в одной записи столбцов;

- название столбца;

- SQL-тип поля;

- количество знаков после запятой в поле.

Объект ResultSetMetaData описывает информацию о количестве, типах и свойствах полей результирующего набора (объекта ResultSet). [24, 48, 48]

Пример:

Опрос количества столбцов:

ResultSetMetaData rsmd = rs.getMetaData(); int col = rsmd.getColumnCount();

Опрос информации о БД:

Connection con = DriverManager.getConnection(url, user, password); DatabaseMetaData meta = con.getMetaData(); System.out.println("Metadaten");

System.out.println("Treibername: " + meta.getDriverName()); System.out.println("Treiberversion: " + meta.getDriverVersion()); System.out.println("Datenbank: " + meta.getDatabaseProductName() +

" " + meta.getDatabaseProductVersion());

Пример(выборка):

Загрузка драйвера (один раз в программе)

Class.forName("oracle.jdbc.driver.OracleDriver");

Установка соединения

Connection con = DriverManager.getConnection(url, user, password);

// Определение запроса (пример) Statement stmt = con.createStatement();

String query = "Select * from Address order by Name";

ResultSet rs = stmt.executeQuery(query);

// Оценка и вывод метаданных к запросу

ResultSetMetaData rsmd = rs.getMetaData(); int col = rsmd.getColumnCount();

for (int i = 1; i <= col; i++)

{System.out.print(rsmd.getColumnName(i) + "\t\t");}

// Вывод результатов запроса while (rs.next())

{for (int i = 1; i <= col; i++){

System.out.print(rs.getObject(i) + "\t\t");}

rs.close(); stmt.close(); con.close();

Пример(добавление записей):

Connection con = DriverManager.getConnection(url, user, password); Statement stmt = con.createStatement();

String query = "Insert into Address" +

"(Id, Name, Vorname, Plz, Ort, Strasse) values (SEQU_ADDRESS.nextVal,'" + name + "','" + vorname + "','" + plz + "','" + ort + "','" + strasse + "')";

System.out.println(query); stmt.execute(query); stmt.close();con.close();

Пример(удаление записей):

Connection con = DriverManager.getConnection(url, user, password); Statement stmt = con.createStatement();

String query = "Delete from Address where Name='" + name + "'"; System.out.println(query);

stmt.execute(query); stmt.close(); con.close();

Для эффективного использования похожих и повторяющихся SQL запросов применяется специальный механизм PreparedStatement. PreparedStatement является подклассом Statement, который хранит прекомпилированный образ SQL выражения. Исполнение этих запросов может происходить несколько быстрее, чем в объектах Statement

Код с использованием Statement:

Statement stmt = con.createStatement();

ResultSet rs = stmt.executeQuery("Select * from test");








Дата добавления: 2015-01-13; просмотров: 1077;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.089 сек.