Всем доброго времени суток. В этой статье, мы возвращаемся к нашему проекту MapWindow GIS, и сегодня мы будем его рассматривать вместе с геокодированием Яндекс.Карт. Это, довольно, популярно сейчас, в свой проект, включать другие ГИС, которые обладают более точными и красочными данными. К ним можно отнести не только Яндекс.Карты, но и тот же самый Google Maps, и многие другие.
В проект, я включил статические Яндекс.Карты, но это вовсе не означает, что они не будут масштабироваться. Да, мы получим карту в виде картинки, но масштабировать ее буде, при помощи MapWindow GIS (компонента TMap).
Я уже рассказывал о работе TClientSocket и TServerSocket на примере MapWindow GIS, в той статье мы рассмотрели: как можно передавать файлы по сети, то есть сервер запрашивает карту у Яндекса, затем отправляет ее клиенту, а в клиенте уже отображается, полученная карта (в компоненте TMap). Но мы не рассмотрели сам механизм, как запрашивает программа-сервер карты у Яндекса.
Данная статья, будет посвящена следующему:
- Настройки, для получения статических карт от Яндекса
- Сохранение статических карт локально на компьютере
- Работа с картами Яндекс локально
- Работа с картами Яндекс, через сеть Интернет
С первым пунктом, я думаю, что Вам понятно. То есть, создается форма с настройками, для получения статической карты. К настройкам можно отнести: работу через прокси; размер, получаемой карты; центр карты; работа с БД (для локальных карт) и другое.
Что касается второго пункта, то тут тоже, должно быть все понятно, то есть, каждую карту, которую мы получаем от Яндекса, мы сохраняем локально на компьютере, чтобы в дальнейшем, можно было с ними работать, без доступа в сеть Интернет (если, конечно, такая функция включена в настройках программы – сохранять карты локально).
Работа с картами Яндекс локально – это возможность, загружать в свой проект, сохраненные карты от Яндекса.
Работа с картами Яндекс, через Интернет – это возможность загружать в свой проект, карты от Яндекса, работать с ними в дальнейшем, при этом ее не сохранять локально, для дальнейшей работы.
В своем проекте, я создал окно с настройками, а также окно для работы с Яндекс.Картами. Окно настроек, у меня, выглядит следующим образом:
Я разделил настройки на 3 подгруппы:
- Настройки сети
- Настройки БД (для локальных карт)
- Настройки, получаемых карт
Все настройки я храню в ini-файле. Работать с данным типом файла очень просто. Пример о том, как работать с ini, я уже немного рассказывал в блоге.
Что касается первого блока – настроек прокси, то здесь необходимо указать, нужные данные для прокси, если карты запрашиваем у Яндекса, через прокси.
Что касается второго блока – настройка БД, то это я сделал для того, чтобы можно было работать с картами локально. В БД сохраняю название улиц, городов, чтобы в дальнейшем, можно было удобно искать локальные (сохраненные) карты от Яндекса.
Программа работает с базой MS Access (по технологии ADO), ее можно подключить самому, либо же создать при помощи программы.
Что касается третьей подгруппы, то там мы просто указываем небольшие настройки, статических карт от Яндекса. Мы уже рассматривали Static API Яндекс.Карт.
Сама форма для работы с Яндекс.Картами, у меня, выглядит следующим образом:
Из данного окна можно запрашивать необходимо информацию у Яндекса, затем занести ее в БД и по нажатию на кнопку «Показать», она отображается в компоненте TMap, с размером, который указан в настройках и, конечно же, с дальнейшим масштабированием.
Кстати, программа может получить еще похожие результаты на Ваш, а Вы из выпадающего списка, можете выбрать нужный:
Как видите, это очень удобно. Давайте посмотрим на то, как я получаю карты от Яндекса, на событие onClick я написал следующий код:
procedure TGeoCoderYandex.Button1Click(Sender: TObject);
var
html,l,query:WideString;
ParsClass:TParserXML;
i:integer;
begin
try
//если выбрана не работа с БД, то запрашиваем у Яндекса данные
if CheckBox1.Checked=False then
begin
//проверяем чтобы пользователь не ввел пустой запрос
if Trim(Edit1.Text)='' then
begin
Application.MessageBox('Введите запрос','Внимание',MB_OK+MB_ICONINFORMATION);
exit;
end;
//загружаем настройки из Setting.ini
if Ini.ReadString('GeoYandex','Proxy','')='True' then
begin
IdHTTP1.ProxyParams.ProxyPort:=Ini.ReadInteger('GeoYandex','ProxyPort',0);
IdHTTP1.ProxyParams.ProxyServer:=Ini.ReadString('GeoYandex','ProxyIP','');
IdHTTP1.ProxyParams.ProxyUsername:=Ini.ReadString('GeoYandex','ProxyUsername','');
IdHTTP1.ProxyParams.ProxyPassword:=Ini.ReadString('GeoYandex','ProxyPassword','');
end;
if Ini.ReadString('GeoYandex','Log','')='True' then
begin
IdHTTP1.Intercept:=IdLogFile1;
IdLogFile1.Filename:=Ini.ReadString('GeoYandex','LogFile','');
IdLogFile1.Active:=True;
end;
Coord:=TStrings.Create;
query:=Edit1.Text;
while (pos(' ',query)<>0) do
begin
Insert('%20',query,pos(' ',query));
Delete(query,pos(' ',query),1);
end;
html:=IdHTTP1.Get('https://geocode-maps.yandex.ru/1.x/?geocode='+AnsiToUtf8(query));
ParsClass:=TParserXML.Create;
ComboBox1.Items:=ParsClass.ParsXMLArr(html,'text');
Coord:=ParsClass.ParsXMLArr(html,'pos');
ComboBox1.ItemIndex:=0;
if ComboBox1.Items.Count<>0 then
begin
ComboBox1.Enabled:=True;
Button2.Enabled:=True;
Button3.Enabled:=True;
end
else
Application.MessageBox('По Вашему запросу ничего не найдено','Внимание',MB_OK+MB_ICONINFORMATION);
end;
//работа с БД а не онлайн
if CheckBox1.Checked=True then
begin
//проверяем чтобы пользователь не ввел пустой запрос
if Trim(Edit1.Text)='' then
begin
Application.MessageBox('Введите запрос','Внимание',MB_OK+MB_ICONINFORMATION);
exit;
end;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('SELECT * FROM Yandex WHERE name LIKE ''%'+Edit1.Text+'%''');
ADOQuery1.Active:=True;
if ADOQuery1.RecordCount=0 then
begin
Application.MessageBox('По Вашему запросу ничего не найдено','Внимание',MB_OK+MB_ICONINFORMATION);
exit;
end;
Coord2:=TStringList.Create;
ADOQuery1.First;
for i:=0 to ADOQuery1.RecordCount-1 do
begin
ComboBox1.Items.Add(ADOQuery1.Fields.Fields[1].AsString);
Coord2.Add('31.010895 52.431881');
ADOQuery1.Next;
end;
ComboBox1.ItemIndex:=0;
ComboBox1.Enabled:=True;
Button2.Enabled:=True;
end;
except
on e:Exception do
begin
FreeAndNil(Coord2);
end;
end;
end;
Здесь, у меня идет различие – пользователь работает с картами локально или же через Интернет.
Также я использую две функции для парсинга данных, я их сам написал, можно было по-другому, но каждому свое:
function TParserXML.ParsXML(XML,tag: WideString): WideString;
begin
Delete(XML,1,pos('<'+tag+'>',XML)+length('<'+tag+'>')-1);
Delete(XML,pos('</'+tag+'>',XML),length(XML));
Result:=XML;
end;
function TParserXML.ParsXMLArr(XML, tag: WideString): TStrings;
var
ParsTag:TParserXML;
i:integer;
begin
try
Result:=TStringList.Create;
ParsTag:=TParserXML.Create;
i:=1;
while (i<=length(XML)) do
begin
if pos('<'+tag+'>',XML)<>0 then
begin
Result.Add(Utf8ToAnsi(ParsTag.ParsXML(XML,tag)));
Delete(XML,1,pos('</'+tag+'>',XML));
i:=0;
end;
inc(i);
end;
ParsTag.Free;
finally
end;
end;
После того, как мы получили url на наше изображение (на нашу карту), то нам необходимо создать само изображение. Я выбрал формат png, так как он лучше всего сжимается и получаю карту следующим образом:
procedure TGeoCoderYandex.Button2Click(Sender: TObject);
var
img:TStringStream;
crd,zoom,pixel:String;
png:TPNGObject;
i:Image;
begin
if CheckBox1.Checked=False then
begin
//создаем PNG-изображение, которое будем грузить с Яндекса
png:=TPNGObject.Create;
//формируем координаты картинки
crd:=Coord.Strings[ComboBox1.ItemIndex];
Insert(',',crd,pos(' ',crd));
Delete(crd,pos(' ',crd),1);
//считываем из INI-файла настройки масштаба и размера картинки
zoom:=Ini.ReadString('GeoYandex','ZoomSize2','');
pixel:=Ini.ReadString('GeoYandex','PixelSize2','');
//запрашиваем картинку на Яндексе
img:=TStringStream.Create(IdHTTP1.Get('https://static-maps.yandex.ru/1.x/?ll='+crd+'&spn='+zoom+'&size='+pixel+'&l=map'));
//загружаем в PNG наш стрим
png.LoadFromStream(img);
//временно его сохраняем
png.SaveToFile(ExtractFilePath(ParamStr(0))+'Yandex\'+crd+'.png');
i:=CoImage.Create;
i.Open(ExtractFilePath(ParamStr(0))+'Yandex\'+crd+'.png',PNG_FILE,False,nil);
//отображаем наше изображение в TMap
Form1.Map1.AddLayer(i,True);
//если пользователем выствалена настройка не хранить все изображения с Яндекса локально, то удаляем их
if Ini.ReadString('GeoYandex','SaveMap','')<>'True' then
begin
//очищаем папку с изображением, кроме последнего, так как он будет в TMap
ClearDir(ExtractFilePath(ParamStr(0))+'Yandex\');
end;
FreeAndNil(png);
FreeAndNil(Coord);
Close;
end;
if CheckBox1.Checked=True then
begin
try
//формируем координаты картинки
crd:=Coord2.Strings[ComboBox1.ItemIndex];
Insert(',',crd,pos(' ',crd));
Delete(crd,pos(' ',crd),1);
i:=CoImage.Create;
i.Open(ExtractFilePath(ParamStr(0))+'Yandex\'+crd+'.png',PNG_FILE,False,nil);
//отображаем наше изображение в TMap
Form1.Map1.AddLayer(i,True);
FreeAndNil(Coord);
Close;
except
on e:Exception do
Application.MessageBox('Не удается отобразить файл','Внимание',MB_OK+MB_ICONINFORMATION);
end;
end;
end;
В итоге, это будет выглядеть следующим образом:
Конечно, отрывки кода из проекта, могут быть не понятны, но смысл должен стать понятным, поэтому подробно, можно почитать, про данную функции, а также сам проект на странице проекта MapWindow GIS в Delphi.
Также хочется внести в проект, еще статические карты Google, ведь у каждого свои предпочтения, правда ведь?