Пример создания базы данных GPS-измерений: различия между версиями

Материал из GIS-Lab
Перейти к навигации Перейти к поиску
Нет описания правки
 
(не показано 16 промежуточных версий этого же участника)
Строка 8: Строка 8:


==Решение==
==Решение==
# Структура  БД
# '''Структура  БД'''
:Gpx  полученные  из  MapSource, обладают  рядом  особенностей:
:Gpx  полученные  из  MapSource, обладают  рядом  особенностей:
:*заполняются  не  все  «поля»
:*заполняются  не  все  «поля»
:*собственное  расширение (<extensions>)
:*собственное  расширение (<extensions>)
:*дата  и  время  для  waypoints  пишется  как  текст  в  элементы  <cmt>  и  <desc>
:*дата  и  время  для  waypoints  пишется  как  текст  в  элементы  <cmt>  и  <desc>
 
Дамп БД:[[Файл:Gpx db 20130407 2315.zip|Дамп БД]]
:Пример  точки:
{{Скрытый
|Рамка = 1px dashed #aa0000
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = Пример  точки
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="XML">
<syntaxhighlight lang="XML">
   <wpt lat="56.8854080" lon="62.2301917">
   <wpt lat="56.8854080" lon="62.2301917">
Строка 28: Строка 34:
     </extensions>
     </extensions>
   </wpt>
   </wpt>
</syntaxhighlight>
</syntaxhighlight>}}
 
В  данном  случае  меня  интересовали: геометрия (lat, lon), имя  (name), высота (ele), дата/время (cmt), символ(sym). Содержание  <desc>  дублирует  <cmt>, с  точки  зрения  MapSource: <cmt> - время, <desc> - комментарий  к  точке, <extensions>  влияет  только  на  отображение  точки  в  MapSource. Символ  <sym>  записывается  как  string, лучше  вынести  в  отдельную  таблицу.
:В  данном  случае  меня  интересовали: геометрия (lat, lon), имя  (name), высота (ele), дата/время (cmt), символ(sym). Содержание  <desc>  дублирует  <cmt>, с  точки  зрения  MapSource: <cmt> - время, <desc> - комментарий  к  точке, <extensions>  влияет  только  на  отображение  точки  в  MapSource. Символ  <sym>  записывается  как  string, лучше  вынести  в  отдельную  таблицу.
{{Скрытый
 
|Рамка = 1px dashed #aa0000
:Структура  таблиц  wpt (waypoints)  и  symtbl (<sym>)
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = Структура  таблиц  wpt (waypoints)  и  symtbl (<sym>)
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="SQL">
<syntaxhighlight lang="SQL">
CREATE TABLE `wpt` (
CREATE TABLE `wpt` (
Строка 43: Строка 53:
   PRIMARY KEY  (`id`))
   PRIMARY KEY  (`id`))
</syntaxhighlight>
</syntaxhighlight>
<br />
<syntaxhighlight lang="SQL">
<syntaxhighlight lang="SQL">
CREATE TABLE `symtbl` (
CREATE TABLE `symtbl` (
Строка 49: Строка 58:
   `desc` varchar(45) NOT NULL,
   `desc` varchar(45) NOT NULL,
   PRIMARY KEY  (`id`))
   PRIMARY KEY  (`id`))
</syntaxhighlight>
</syntaxhighlight>}}
<br />
{{Скрытый
:Пример  трека:
|Рамка = 1px dashed #aa0000
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = Пример  трека
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="XML">
<syntaxhighlight lang="XML">
   <trk>
   <trk>
Строка 67: Строка 81:
     </trkseg>
     </trkseg>
   </trk>
   </trk>
</syntaxhighlight>
</syntaxhighlight>}}
<br />
Трек  имеет  только  имя  и  множество  точек, тип  которых – wptType, но  с  более  аскетичным  содержанием. Здесь  надо  заметить, что  элемент  <time>  содержит  время  в  Univeral Coordinated Time (UTC), в  отличии  от  локального  в  <cmt>, следует  выбрать  единое  время  для  БД  и  привести  к  нему  все  значения. Для  удобства  следует  получить  linestring, для  отображения  трэка, но  желательно  сохранить  время  для  каждой  точки  трэка. Также  удобно  знать  время  трэка, по  первой  точке. Для  трэков  с  одной  точкой  поле  trk_line=null. Также  надо  учитывать, что  трэк  может  содержать  несколько  сегментов (Track Segment), хотя  MapSource  кажется, так  не  делает, вместо  этого  создавая  новый  трэк. Создадим  таблицы, для  треков  и  точек  треков, у  последних  получится  два  внешних  ключа  trk_id  и  nseg, хотя  nseg  получается  «висячим» - так  как  никуда  не  указывает…
:Трек  имеет  только  имя  и  множество  точек, тип  которых – wptType, но  с  более  аскетичным  содержанием. Здесь  надо  заметить, что  элемент  <time>  содержит  время  в  Univeral Coordinated Time (UTC), в  отличии  от  локального  в  <cmt>, следует  выбрать  единое  время  для  БД  и  привести  к  нему  все  значения. Для  удобства  следует  получить  linestring, для  отображения  трэка, но  желательно  сохранить  время  для  каждой  точки  трэка. Также  удобно  знать  время  трэка, по  первой  точке. Для  трэков  с  одной  точкой  поле  trk_line=null. Также  надо  учитывать, что  трэк  может  содержать  несколько  сегментов (Track Segment), хотя  MapSource  кажется, так  не  делает, вместо  этого  создавая  новый  трэк. Создадим  таблицы, для  треков  и  точек  треков, у  последних  получится  два  внешних  ключа  trk_id  и  nseg, хотя  nseg  получается  «висячим» - так  как  никуда  не  указывает…
{{Скрытый
 
|Рамка = 1px dashed #aa0000
:Структура  таблиц  trk(tracklogs) и  trkpt (Track Point)
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = Структура  таблиц  trk(tracklogs) и  trkpt (Track Point)
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="SQL">
<syntaxhighlight lang="SQL">
CREATE TABLE `trk` (
CREATE TABLE `trk` (
Строка 90: Строка 108:
   `ele` double default NULL,
   `ele` double default NULL,
   PRIMARY KEY  (`id`))
   PRIMARY KEY  (`id`))
</syntaxhighlight>
</syntaxhighlight>}}
:Функция для заполнения `trk_line`
Я это называю - "собирать бисер". В SFA нет функций для редактирования геометрии (в PostGIS и Oracle Spatila - есть). По хорошему надо использовать WKB - но как сделать это на SQL - я не знаю. Поэтому использую WKT и колдую с текстом (longText, по началу использовал text - как то не хватило...). У MySQL есть пара неприятных моментов связанных с геометрией: при попытке создать в хранимке определённую геометрию (например LINESTRING) - MySQL меняет функцию на создание просто геометрии (и внезапно получаем MULTIPOINT, хотя может это косяк моей версии), поэтому я использовал geomfromtext и в строке явно указывал тип геометрии. При объявлении "Declare p1, p2 point;" p1, p2 - это указатели, а значит при set p1=p2 мы получаем два указателя на '''один''' объект. Что бы скопировать точку приходится городить такое : Set p1 = geomfromtext(concat('Point(', X(CrP), ' ', Y(CrP), ')'));
{{Скрытый
|Рамка = 1px dashed #aa0000
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = CreateTrkLine
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="SQL">
PROCEDURE `CreateTrkLine`(nid int)
BEGIN
  Declare done int default 0;
  declare coup, i int default 0;
  Declare p1, p2, CrP point;
  Declare CrLn LineString;
  Declare Cur1 Cursor for
  SELECT p FROM `gpx_db`.`trkpt` where trk_id=nid and nseg=1;
  Declare Continue Handler For not found set done = 1;
 
  Open Cur1;
  Repeat
  Fetch Cur1 into CrP;
    if Not Done then
    case i
      when 0 then
      Set p1 = geomfromtext(concat('Point(', X(CrP), ' ', Y(CrP), ')'));
      when 1 then
      Set CrLn = geometryfromtext(concat('LineString(',x(p1),' ',y(p1),',',x(CrP),' ',y(CrP),')'));
      else
      Set CrLn = `LS_AddPoint`(CrLn, CrP);
    end case;
    Set i=i+1;
    End if;
  Until done End Repeat;
  Close Cur1;
 
  update trk set `trk_line`=CrLn where id=nid;
END $$
</syntaxhighlight>}}
{{Скрытый
|Рамка = 1px dashed #aa0000
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = Функция для добавления Point к LineString
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="SQL">
FUNCTION `LS_AddPoint`(Ls LineString, np point) RETURNS linestring
BEGIN
  Declare I, ICount Integer default 1;
  Declare nStr longText;
  Declare crP Point;
  Set ICount = NumPoints(Ls) + 1;
  Set nStr = 'LineString(';
  while I < ICount do
  Set crP = PointN(Ls, I);
  Set nStr = Concat(nStr, X(crP), ' ', Y(crP), ',');
  set I = I + 1;
  end while;
  Set nStr = Concat(nStr, X(nP), ' ', Y(nP), ')');
  Return LineFromText(nStr);
END $$
</syntaxhighlight>}}
<br />
# '''Импорт  данных'''
Для  разработки  модуля  импорта  данных, я  выбрал  VBA, по  двум  причинам: наиболее  удобный  IDE  из  доступных  у  меня  на  рабочей  машине; наличие  опыта  и  наработок. Перед  началом  работы, необходимо  подключить  Microsoft  XML  v6.0 (работа  с  XML)  и  Microsoft ActiveX Data Objects 2.8 Library (подключение  БД). Также  я  использовал  WinAPI, а  именно  GetOpenFileNameA  из  comdlg32.dll.
Изначально, было решено, разделить чтение и запись, что бы передать данные используются структуры: wpt_rec и trk_rec. В начале разработки, в отладочных целях, данные записывались на Лист в Excel'е - данный код приведён в листингах, но закомментирован. Некрасиво получилось то, что фильтрация исходных данных происходить в разных местах: для точек - при чтении XML'я (If cWPT.cmt <> "" Then 'У "ненужных" точек cWPT.cmt=""), для треков в начале записи в БД (If nTRK.s(0).p(0).time <> "" Then). Так же разделено преобразование даты/время, но здесь это оправданно - как было сказано выше, в точках и трэках время записано по разному.
:Запуск импорта - test1.
<br />
<br />
# Импорт  данных
Файл с макросами (xlsm):[[Файл:Imp_gpx.zip|файл с макросами (xlsm)]]
:Для  разработки  модуля  импорта  данных, я  выбрал  VBA, по  двум  причинам: наиболее  удобный  IDE  из  доступных  у  меня  на  рабочей  машине; наличие  опыта  и  наработок. Перед  началом  работы, необходимо  подключить  Microsoft  XML  v6.0 (работа  с XML)  и  Microsoft ActiveX Data Objects 2.8 Library (подключение  БД). Также  я  использовал  WinAPI, а  именно  GetOpenFileNameA  из  comdlg32.dll.
<br />
<br />
:Обработка XML'я
{{Скрытый
|Рамка = 1px dashed #aa0000
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = Обработка XML'я
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="VB">
<syntaxhighlight lang="VB">
'Переменные для записи данных на Лист
'Переменные для записи данных на Лист
Строка 278: Строка 370:
  'InsTRK cTRK
  'InsTRK cTRK
End Sub
End Sub
</syntaxhighlight>
</syntaxhighlight>}}
<br />
{{Скрытый
:Загрузка в БД
|Рамка = 1px dashed #aa0000
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = Загрузка в БД
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="VB">
<syntaxhighlight lang="VB">
Dim MyConnect As ADODB.Connection
Dim MyConnect As ADODB.Connection
Строка 398: Строка 495:
  Next i
  Next i
End Sub
End Sub
</syntaxhighlight>
</syntaxhighlight>}}
<br />
{{Скрытый
:OpenFile
|Рамка = 1px dashed #aa0000
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = OpenFile
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="VB">
<syntaxhighlight lang="VB">
Private Const OFN_ALLOWMULTISELECT As Long = &H200
Private Const OFN_ALLOWMULTISELECT As Long = &H200
Строка 501: Строка 603:
   End With
   End With
End Function
End Function
</syntaxhighlight>
</syntaxhighlight>}}


==Использование==
==Использование==

Текущая версия от 19:35, 12 июля 2013

Эта страница является черновиком статьи.


Задача

Дано: Имеется много gpx-файлов, полученные из MapSource (BaseCamp)

Получить: Собрать все данные (точки (waypoints) и трэки (tracklogs)) в одном месте. Отсеяв дубли, «ненужные» точки.

Ресурсы: MySQL Server 5.0.67-community-nt via TCP/IP; MySQL GUI 5.1.11; MySQL Connector/ODBC 5.1.12; Microsoft Office 2007

Решение

  1. Структура БД
Gpx полученные из MapSource, обладают рядом особенностей:
  • заполняются не все «поля»
  • собственное расширение (<extensions>)
  • дата и время для waypoints пишется как текст в элементы <cmt> и <desc>

Дамп БД:Файл:Gpx db 20130407 2315.zip


В данном случае меня интересовали: геометрия (lat, lon), имя (name), высота (ele), дата/время (cmt), символ(sym). Содержание <desc> дублирует <cmt>, с точки зрения MapSource: <cmt> - время, <desc> - комментарий к точке, <extensions> влияет только на отображение точки в MapSource. Символ <sym> записывается как string, лучше вынести в отдельную таблицу.



Трек имеет только имя и множество точек, тип которых – wptType, но с более аскетичным содержанием. Здесь надо заметить, что элемент


Функция для заполнения `trk_line`

Я это называю - "собирать бисер". В SFA нет функций для редактирования геометрии (в PostGIS и Oracle Spatila - есть). По хорошему надо использовать WKB - но как сделать это на SQL - я не знаю. Поэтому использую WKT и колдую с текстом (longText, по началу использовал text - как то не хватило...). У MySQL есть пара неприятных моментов связанных с геометрией: при попытке создать в хранимке определённую геометрию (например LINESTRING) - MySQL меняет функцию на создание просто геометрии (и внезапно получаем MULTIPOINT, хотя может это косяк моей версии), поэтому я использовал geomfromtext и в строке явно указывал тип геометрии. При объявлении "Declare p1, p2 point;" p1, p2 - это указатели, а значит при set p1=p2 мы получаем два указателя на один объект. Что бы скопировать точку приходится городить такое : Set p1 = geomfromtext(concat('Point(', X(CrP), ' ', Y(CrP), ')'));




  1. Импорт данных

Для разработки модуля импорта данных, я выбрал VBA, по двум причинам: наиболее удобный IDE из доступных у меня на рабочей машине; наличие опыта и наработок. Перед началом работы, необходимо подключить Microsoft XML v6.0 (работа с XML) и Microsoft ActiveX Data Objects 2.8 Library (подключение БД). Также я использовал WinAPI, а именно GetOpenFileNameA из comdlg32.dll. Изначально, было решено, разделить чтение и запись, что бы передать данные используются структуры: wpt_rec и trk_rec. В начале разработки, в отладочных целях, данные записывались на Лист в Excel'е - данный код приведён в листингах, но закомментирован. Некрасиво получилось то, что фильтрация исходных данных происходить в разных местах: для точек - при чтении XML'я (If cWPT.cmt <> "" Then 'У "ненужных" точек cWPT.cmt=""), для треков в начале записи в БД (If nTRK.s(0).p(0).time <> "" Then). Так же разделено преобразование даты/время, но здесь это оправданно - как было сказано выше, в точках и трэках время записано по разному.

Запуск импорта - test1.


Файл с макросами (xlsm):Файл:Imp gpx.zip




Использование

QGIS
AutoCAD Map 3D

Ссылки

gpx.xsd
MapSource
GpxExtensions