Как в Delphi / Lazarus / С++ Builder работать с картами в формате SHP

SHP

ShapeFile, они же «Шейпы» (англ. Shape — Фигура) представляют собой фигуру или набор фигур (возможно не связанных между собой) сложных форм. Фигуры бывают в виде точек, полилиний или полигонов.

Стоит также отметить, что вместе с файлом формата "*.shp" формируется файл формата "*.dbf" хранящий в себе заголовочную информацию о наших шейпах. Важно, чтобы файл "*.dbf" имел такое же название, что и файл ".shp". В главном файле .shp хранятся геометрические данные, индексированные в файле .shx (индекс) и расширенные атрибутами и их значениями в базе данных формата dBASE (.dbf). Публикации ESRI имеет полную спецификацию формата "шейп-файлов" (.shp, .shx, .dbf) и использует полноценную поддержку среди целого ряда ГИС и САПР, широко применяется для представления всевозможных карт и картографических схем-слоев.

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

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

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

В контексте ГИС векторные форматы данных (или по сути – векторные модели хранения данных) являются одним из способов отображения объектов реального мира.

Вы можете открыть файлы SHP с помощью следующих программ: CADE Pro, Parallels, Tools Center, AutoCAD, ESRI's ArcExplorer, Free File Viewer Pro.

Преимущества шейп-файлов

Недостатки шейп-файлов

Шейп-файлы подходят для хранения простой геометрии пространственных объектов. Однако имеются серьезные проблемы, связанные с хранением атрибутов. Например, они не могут округлять числа, имеют ограниченную поддержку символов Unicode, не могут хранить поля, имена которых длиннее 10 знаков, и не могут хранить дату и время в одном поле. Это только основные ограничения. Кроме того, они не поддерживают возможности, присутствующие в базах геоданных, например, работу с доменами и подтипами. Поэтому, не следует использовать шейп-файлы, если вы хотите хранить сложные атрибуты и пользоваться возможностями, предоставляемыми базами геоданных.

Ограничения по геометрии Shape-файлов

Каждый файл-компонент шейп-файла не может быть более 2 GB, что составляет примерно 70 миллионов точечных объектов, потому что для ссылок внутри файла используются 4-байтные числа. Количество линейных или полигональных объектов, которые могут содержаться в шейп-файле, зависит от числа вершин этих объектов (вершина является эквивалентом точки).

В классах объектов базы геоданных значения допуска (x;y) хранится напрямую, в шейп-файлах совершенно по-другому. Допуск по (x;y) – это минимальное расстояние между координатами, ближе которого они будут считаться идентичными. Между пространственными объектами одного класса объектов, или между объектами нескольких различных классов при оценке взаимосвязей используется тот самый допуск. Также он активно используется при редактировании объектов. Если вы используете такие операции и инструменты как: Наложение (Overlay), Вырезать (Clip), Выбрать в слое по расположению (Select Layer By Location), или любой инструмент, который использует в качестве входных данных два или более класса пространственных объектов, то вместо шейп-файлов лучше использовать класс объектов базы геоданных(где доступ осуществляется по x, y).

Шейп-файл может занимать от трех до пяти раз больше места, по сравнению с файловой базой геоданных или SDE, поскольку использует иные методы сжатия.

Шейп-файлы поддерживают объекты-мультипатчи, но не поддерживают следующие возможности мультипатчей:

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

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

В отличие от других форматов, шейп-файл хранит числовые атрибуты в символьном, а не бинарном формате. Для реальных числовых значений (например, с десятичными знаками), это может привести к ошибкам из-за округления. Это ограничение касается только атрибутов, и не относится к хранению координат.

Ещё больше информации о ShapeFile можно узнать тут.

А вот про особенности работы в этом формате подробнее можно прочитать здесь.

Как создать файл в формате SHP с помощью кода

Про сам формат поговорили и как готовые файлы открыть узнали, а как работать в Delphi? Тут есть три пути:

  1. Использовать GDAL - это библиотека переводчиков для растровых и векторных форматов геопространственных данных, которая выпускается под лицензией X / MIT style Open Source Open Source Geospatial Foundation . В качестве библиотеки он представляет одну растровую абстрактную модель данных и одну векторную абстрактную модель данных вызывающему приложению для всех поддерживаемых форматов. Он также поставляется с различными полезными утилитами командной строки для перевода и обработки данных. Вот статья по работе с данной библиотекой
  2. Воспользоваться MapWindow GIS — это проект с открытым исходным кодом ГИС, который обладает набором программных и программируемых библиотек. Он разработан университетом GeoSpatial Software Lab штата Айдахо. Приложение запускается только под операционной системой Windows, на linux поддержки нет. Прежде всего данный проект очень интересен разработчикам, т.к. само ядро данного приложения написано на С++ и представляет собой библиотеку ActiveX, которую можно использовать отдельно от MapWindow и разрабатывать собственные приложения для возможности визуализации и обработки геоданных (работает во всех средах разработки, которые поддерживают импорт ActiveX компонентов). Вот ссылка на гитхаб.
  3. А самый лучший вариант использовать FastReport. А чем? Тем, что он уже готов к использованию! Берёте и вот прямо сразу загружаете - и, О ЧУДО, он уже вам всё показывает! Это как с уткой по-Пекински! Если бы вы готовили её сами, то вам пришлось бы её неделю мариновать, а в нашем случае - мы её уже замариновали для вас. Приходите и сразу кушаете!

Создаём файл с картой в формате SHP

Заходим в FR Designer. Находим Object “Map” и добавляем его в документ.

FR Дизайнер

Должен появиться вот такой редактор карт. Первая вкладка - это общие сведения.

Редактор карт

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

Add - загрузить файл в формате shp, osm или gpx (В нашем случае SHP).

Delete - удалить слой карты.

Keep Aspect Ratio - сохранить соотношение сторон карты.

Mercator Projection - использование проекции Меркатора.

Для добавления нового слоя нажмите кнопку "Добавить...". Будет показано следующее окно:

На этом шаге нужно выбрать тип слоя:

- карта из файла (.shp/.dbf, .osm, .gpx). Это наиболее часто используемый тип карт. К примеру, вы можете напечатать карту мира и выделить цветом страны, в которых продажи были больше определенного значения;

- пустой слой с геоданными представленными программой. Ваше приложение должно предоставлять географические координаты (пару значений - широта и долгота), которые будут отображены в виде точки на карте. Точка может иметь подпись, а также быть разного размера и/или цвета, в зависимости от некоторых данных. На практике этот тип карты используется в качестве второго слоя (первый слой, базовый, берется из файла карты). Например, базовый слой отображает карту какой-либо страны, а второй слой - точки с названиями городов, в которых были продажи. Размеры и цвет точки можно настроить таким образом, чтобы был понятен уровень продаж в данном городе.

Если вы выбрали слой на основе файла карты, укажите дополнительно, как хранить картографические данные:

- данные внедряются в файл отчета. При этом отчет может сильно увеличиться в размерах.

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

Карты большого объема (более 30Мб) или с большим количеством полигонов (более 20000) серьезно замедлят работу отчета.

Редактор заливкиПри нажатии на Fill мы попадаем в редактор заливки. Во вкладке Кисть есть 3 свойства:

Brush style

Стиль кисти имеет несколько готовых видов форматирования:

Solid - заливка единым цветом;

Clear - чистый фон без цвета;

Horizontal - горизонтальные линии на весь фон;

Vertical - вертикальные линии на весь фон;

Forward Diagonal - диагональные линии на весь фон;

Backward Diagonal - обратно диагональные линии на весь фон;

Cross - перекрёстные линии на весь фон;

Diagonal cross - диагональные перекрёстные линии на весь фон;

Цвет фона Цвет первого плана

Цвет фона, как и цвет переднего плана можно выбрать из готовой палитры цветов или настроить необходимый цвет нажав на Other.

Редактор цвета

Во второй вкладке у нас настройки градиента для фона.

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

Начальный и конечный цвет можно выбрать из готовой палитры цветов или настроить необходимый цвет нажав на Other.

Стиль градиента Стиль градиента

В третьей вкладке настройки заливки в виде стекла.

Имеется выбор ориентации: вертикальный, горизонтальный, вертикальное и горизонтальное зеркало.

Цвет можно выбрать из готовой палитры или настроить необходимый цвет нажав на Other.

Blend - коэффициент смешивания цветов (на скриншоте равен 0,5).

Show hatch - отображение штриховки.

Редактор заливки в виде стекла Редактор заливки в виде стекла

Вернёмся в редактор карты и найдём уже редактор рамок.

Блок линий: можно выбрать стиль из предложенных вариантов, задать ширину линии и выбрать цвет.

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

Добавляя тень мы также можем указать ширину и цвет.

Редактор рамок Редактор рамок

Пример цветовой шкалы

Теперь рассмотрим вторую вкладку в редакторе карт - Шкала цветов.

Цвет рамки можно выбрать из готовой палитры цветов, установив ширину рамок. Выставляем позицию шкалы. На примере у нас расположение в правом нижнем углу.

Название шкалы вписываем в поле Text, через Font… настроим шрифт и его размер.

Вкладка Размер шкалы по виду не отличается от Цвета шкалы, поэтому повторяться не буду.

Редактор карты

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

Пример карты в отчёте

Создаём карту в формате SHP с помощью кода

Сохранение в SHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
procedure TForm1.FormCreate(Sender: TObject);
var page: TfrxReportPage;
 map: TfrxMapView;
 layer: TfrxMapFileLayer;
 applayer: TfrxApplicationLayer;
begin
 page := TfrxReportPage(frxReport1.FindObject('Page1'));
 map := TfrxMapView.Create(page);
 with map do
 begin
 CreateUniqueName();
 SetBounds(0, 0, 700, 800);
 MaxZoom := 50;
 MinZoom := 1;
 KeepAspectRatio := True;
 MercatorProjection := True;
 with ColorScale do
 begin
 Visible := True;
 BorderColor := 0;
 BorderWidth := 1;
 Dock := sdBottomRight;
 FillColor := 16777215;
 ValueFormat := '%1.0f';
 with Font do
 begin
 Charset := 1;
 Color := -16777208;
 Height := -13;
 Name := 'Tahoma';
 Style := [];
 end;
 with TitleFont do
 begin
 Charset := 1;
 Color := -16777208;
 Height := -13;
 Name := 'Tahoma';
 Style := [];
 end;
 end;
 with SizeScale do
 begin
 Visible := True;
 BorderColor := 0;
 BorderWidth := 1;
 Dock := sdTopLeft;
 FillColor := 16777215;
 ValueFormat := '%1.0f';
 with Font do
 begin
 Charset := 1;
 Color := -16777208;
 Height := -13;
 Name := 'Tahoma';
 Style := [];
 end;
 with TitleFont do
 begin
 Charset := 1;
 Color := -16777208;
 Height := -13;
 Name := 'Tahoma';
 Style := [];
 end;
 end;
 end;
 layer := TfrxMapFileLayer.Create(map);
 with layer do
 begin
 CreateUniqueName();
 MapFileName := 'C:\Program Files (x86)\FastReport 6 VCL Enterprise\Demos\Main\Maps\world.shp';
 DataSet := MapOrderDetailsDS;
 LabelColumn := 'NAME';
 SpatialColumn := 'NAME';
 ZoomPolygon := 'Germany';
 LabelKind := mlName;
 MapPalette := mpNone;
 MapAccuracy := 0;
 PixelAccuracy := 0;
 HighlightColor := 65280;
 Operation := opSum;
 ValueFormat := '%1.0f';
 PointLabelsVisibleAtZoom := 1;
 with ColorRanges do
 begin
 RangeFactor := rfValue;
 RangeCount := 0;
 Visible := True;
 StartColor := 255;
 MiddleColor := 65535;
 EndColor := 32768;
 end;
 with SizeRanges do
 begin
 RangeFactor := rfValue; {uses frxMapRanges}
 RangeCount := 0;
 Visible := True;
 StartSize := 4;
 EndSize := 20;
 end;
 end;
 applayer := TfrxApplicationLayer.Create(map);
 applayer.CreateUniqueName();
 with applayer do
 begin
 DataSet := MapOrderDetailsDS;
 AnalyticalValue := '<MapOrderDetails."UnitPrice"> * <MapOrderDetails."Quantity"> * (1 - <MapOrderDetails."Discount">)';
 Filter := '<MapOrders."ShipCountry"> = ''Germany''';
 HighlightColor := 65280;
 Operation := opSum;
 ValueFormat := '%1.0f';
 LabelKind := mlName;
 MapPalette := mpNone;
 PointLabelsVisibleAtZoom := 1;
 LabelValue := '<MapOrders."ShipCity">';
 LatitudeValue := '<MapOrders."Latitude">';
 LongitudeValue := '<MapOrders."Longitude">';
 SizeRanges.RangeFactor := rfValue;
 SizeRanges.RangeCount := 3;
 SizeRanges.Visible := True;
 SizeRanges.StartSize := 8;
 SizeRanges.EndSize := 20;
 ColorRanges.RangeFactor := rfValue;
 ColorRanges.RangeCount := 3;
 ColorRanges.Visible := True;
 ColorRanges.StartColor := 255;
 ColorRanges.MiddleColor := 65535;
 ColorRanges.EndColor := 32768;
 end;
 frxReport1.ShowReport;
end;

Shape далеко не единственный формат для работы с картами, существуют ещё OpenStreetMap (OSM) и GPS eXchange Format, но о них я расскажу в других статьях.