Еще один маленький вклад в нашу программу.
Итак добавляем в планету границы стран, регионов, муниципальных образований и так далее и тому подобное.
Скачивание границ.1.Для начала открываем сайт с границами
OSM Boundaries Map 4.2 и скачиваем свежую версию границ.
https://wambachers-osm.website/boundaries/2. Выбираем
регион. Например РФ.
3. Формат экспорта
json.
4. Ставим режим
split - каждая граница в отдельный файл. (Вся Россия влезает в один файл 300МБ, но стандартный парсер JSON на таком файле обламывается.)
5. Нажимаем кнопку экспорт и получаем запрос.
- Код: Выделить всё
https://wambachers-osm.website/boundaries/exportBoundaries?apiversion=1.0&apikey=###############&exportFormat=json&exportLayout=split&exportAreas=water&from_al=2&to_al=4&union=false&selected=60189
6. Вводим его в адресной строке
7. Ставим максимальные уровни
from_al=2&to_al=108. Из полученного архива извлекаем все файлы.
9. Раскладываем файлы по подпапкам (в соответствии с уровнем
#AL2 ...
#AL10)
Парсинг GeoJson.Осторожно, С++!- скрытый текст: показать
- 1. Восстанавливаем древовидную структуру. Создаем класс объекта.
- Код: Выделить всё
class TBoundaryTreeNode : public TTreeNode
{
public:
int ID;
UnicodeString TimeStamp;
UnicodeString Name;
int AdminLevel;
TIntegerDynArray PolyIndex;
TIntegerDynArray ContourIndex;
TIntegerDynArray ContourLength;
TDoubleDynArray XCoord;
TDoubleDynArray YCoord;
};
2.Берем стандартный TTreeView и прописываем в обработку события OnCreateNodeClass наш класс
- Код: Выделить всё
void __fastcall TForm1::TVCreateNodeClass(TCustomTreeView *Sender, TTreeNodeClass &NodeClass)
{
NodeClass = __classid(TBoundaryTreeNode);
}
3.Составляем список файлов
- Код: Выделить всё
TStringDynArray list = TDirectory::GetFiles(Edit1->Text, "*.GeoJson", TSearchOption::soAllDirectories);
4. Парсим файлы по списку
- Код: Выделить всё
TV->Visible = false;
TV->Items->Clear();
TV->Items->Add(NULL, "Административные границы");
ProgressBar1->Position = 0;
ProgressBar1->Max = list.Length;
for(int i = 0; i < list.Length; i++)
{
ProgressBar1->Position = i;
ParseFile(list[i]);
}
TV->AutoExpand = true;
TV->Visible = true;
Beep();
5. Код парсера
- Код: Выделить всё
void __fastcall TForm1::ParseFile(UnicodeString FileName)
{
int R, i, j, k, l, Cnt, index;
int PointIndex, LineIndex;
int ID = 0;
TByteDynArray FileBuf;
UnicodeString TimeStamp = "";
UnicodeString Name = "";
int AdminLevel = 0;
UnicodeString Wikidata = "";
UnicodeString Wikipedia = "";
int Population = -1;
UnicodeString PopulationDate = "";
TJSONObject* JsonObj;
TJSONObject* PropObj;
TJSONObject* TagsObj;
TJSONArray* RPathObj;
TBoundaryTreeNode* PNode = NULL;
TBoundaryTreeNode* CNode = NULL;
TJSONObject* RGeomObj;
TJSONArray* RCoordObj;
TJSONArray* RPolyObj;
TJSONArray* RLineObj;
TJSONArray* RPointObj;
FileBuf = TEncoding::UTF8->GetBytes(TFile::ReadAllText(FileName));
JsonObj = (TJSONObject*)TJSONObject::ParseJSONValue(FileBuf, 0);
if(JsonObj != NULL)
{
RPathObj = (TJSONArray*)JsonObj->GetValue("rpath");
PNode = (TBoundaryTreeNode*)TV->Items->Item[0];
CNode = NULL;
if(RPathObj->Count > 1)
{
for(i = RPathObj->Count - 2; i >= 0; i--)
{
R = RPathObj->Get(i)->Value().ToInt();
index = -1;
Cnt = PNode->Count;
for(j = 0; j < Cnt; j++)
{
CNode = (TBoundaryTreeNode*)(PNode->Item[j]);
if(CNode->ID == R)
{
PNode = CNode;
index = j;
break;
}
}
if(index < 0)
{
CNode = (TBoundaryTreeNode*)TV->Items->AddChild(PNode, "");
CNode->ID = R;
if(CNode->Text == "") CNode->Text = L"no name";
PNode = CNode;
}
}
}
if(CNode !=NULL)
{
ID = JsonObj->GetValue("id")->Value().ToInt();
TimeStamp = JsonObj->GetValue("timestamp")->Value();
PropObj = (TJSONObject*)JsonObj->GetValue("properties");
Name = Utf8ToAnsi(PropObj->GetValue("localname")->Value());
AdminLevel = PropObj->GetValue("admin_level")->Value().ToInt();
TagsObj = (TJSONObject*)PropObj->GetValue("tags");
//if(TagsObj->FindValue("wikidata") != NULL) Wikidata = TryGetValue("wikidata")->Value();
//if(TagsObj->FindValue("wikipedia") != NULL) Wikipedia = Utf8ToAnsi(TagsObj->GetValue("wikipedia")->Value());
//if(TagsObj->FindValue("population") != NULL) Population = TagsObj->GetValue("population")->Value().ToInt();
//if(TagsObj->FindValue("population:date") != NULL) PopulationDate = TagsObj->GetValue("population:date")->Value();
CNode->Text = Name;
CNode->ID = ID;
PointIndex = 0;
LineIndex = 0;
CNode->ContourIndex.set_length(0);
CNode->ContourLength.set_length(0);
CNode->XCoord.set_length(0);
CNode->YCoord.set_length(0);
RGeomObj = (TJSONObject*)JsonObj->GetValue("geometry");
RCoordObj = (TJSONArray*)RGeomObj->GetValue("coordinates");
CNode->PolyIndex.set_length(RCoordObj->Count);
for(i = 0; i < RCoordObj->Count; i++)
{
RPolyObj = (TJSONArray*)RCoordObj->Items[i];
CNode->PolyIndex[i] = RPolyObj->Count;
CNode->ContourIndex.set_length(CNode->ContourIndex.get_length() + RPolyObj->Count);
CNode->ContourLength.set_length(CNode->ContourLength.get_length() + RPolyObj->Count);
for(j = 0; j < RPolyObj->Count; j++)
{
RLineObj = (TJSONArray*)RPolyObj->Items[j];
CNode->ContourIndex[LineIndex] = PointIndex;
CNode->ContourLength[LineIndex] = RLineObj->Count;
CNode->XCoord.set_length(CNode->XCoord.get_length() + RLineObj->Count);
CNode->YCoord.set_length(CNode->YCoord.get_length() + RLineObj->Count);
for(k = 0; k < RLineObj->Count; k++)
{
RPointObj = (TJSONArray*)RLineObj->Items[k];
CNode->XCoord[PointIndex] = RPointObj->Get(0)->Value().ToDouble();
CNode->YCoord[PointIndex] = RPointObj->Get(1)->Value().ToDouble();
PointIndex++;
}
LineIndex++;
}
}
}
delete JsonObj;
}
}