Импорт Административно-территориального деления

программа для загрузки и просмотра спутниковых снимков Земли, Луны, Марса предоставленных сервисами Google Maps и Космоснимки. Возможность работы с GPS приёмником.

Модератор: Tolik

Аватара пользователя
DJ VK
Гуру
Сообщения: 1468
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 80 раз
Поблагодарили: 314 раз

Импорт Административно-территориального деления

Сообщение DJ VK »

Еще один маленький вклад в нашу программу.

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

Скачивание границ.

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=10
8. Из полученного архива извлекаем все файлы.
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;
	}
}
Последний раз редактировалось DJ VK 04 июл 2017, 15:51, всего редактировалось 1 раз.
Аватара пользователя
DJ VK
Гуру
Сообщения: 1468
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 80 раз
Поблагодарили: 314 раз

Re: Импорт Административно-территориального деления

Сообщение DJ VK »

Экспорт в KML
Если кому-то понадобится.

Вместо массивов double координат используем

Код: Выделить всё

TStringDynArray Coord;
парсинг координат в строку

Код: Выделить всё

CNode->Coord[PointIndex] = RPointObj->Get(0)->ToString() + L"," + RPointObj->Get(1)->ToString() + L",0 ";
//CNode->XCoord[PointIndex] = RPointObj->Get(0)->Value().ToDouble();
//CNode->YCoord[PointIndex] = RPointObj->Get(1)->Value().ToDouble();
1. Экспорт дерева

Код: Выделить всё

       _di_IXMLDocument XMLDocument = NewXMLDocument();
	XMLDocument->Active = True;
	XMLDocument->Encoding = "UTF-8";

	_di_IXMLNode RootElement = XMLDocument->AddChild(L"kml", L"http://earth.google.com/kml/2.2");
	_di_IXMLNode DocElement = RootElement->AddChild(L"Document");

	AddNode(DocElement, (TBoundaryTreeNode*)TV->Items->Item[0]);

	XMLDocument->SaveToFile(Edit1->Text +"Output.KML");
	XMLDocument = NULL;
	Beep();
2. Процедуры

Код: Выделить всё

//---------------------------------------------------------------------------
void __fastcall TForm1::AddNode(_di_IXMLNode ParentXML, TBoundaryTreeNode* Node)
{
	int i;  //int i,j,k,l;
	TBoundaryTreeNode* ChildNode;
	_di_IXMLNode FolderElement;
	GenerateNames(Node);

	if(Node->Count == 0) FolderElement = ParentXML;
	else FolderElement = AddFolder(ParentXML);

	if(Node->PolyIndex.get_length() > 0) AddPlacemark(FolderElement, Node);

	if(Node->Count > 0)
	{
		for(i = 0; i < Node->Count; i++)
		{
			ChildNode = (TBoundaryTreeNode*)Node->Item[i];
			AddNode(FolderElement, ChildNode);
		}
  }

}
//---------------------------------------------------------------------------
_di_IXMLNode __fastcall TForm1::AddFolder(_di_IXMLNode ParentXML)
{
	_di_IXMLNode Folder;
	_di_IXMLNode Child1;
	_di_IXMLNode Child2;
	_di_IXMLNode Child3;

	Folder = ParentXML->AddChild(L"Folder");
	Child1 = Folder->AddChild(L"name");
	Child1->SetText(FolderName);
	Child1 = Folder->AddChild(L"open");
	Child1->SetText(L"1");
	Child1 = Folder->AddChild(L"style");
	Child2 = Child1->AddChild(L"ListStyle");
	Child3 = Child2->AddChild(L"listItemType");
	Child3->SetText(L"check");
	Child3 = Child2->AddChild(L"bgColor");
	Child3->SetText(L"00ffffff");

	return Folder;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::AddPlacemark(_di_IXMLNode ParentXML, TBoundaryTreeNode* Node)
{
	int i,j,k;
	int LineIndex, PolyCnt, LineCnt, PointCnt;
	_di_IXMLNode Placemark;
	_di_IXMLNode Child1;
	_di_IXMLNode Child2;
	_di_IXMLNode Child3;
	_di_IXMLNode Child4;
	_di_IXMLNode Child5;
	UnicodeString CoordStr;
	UnicodeString Str;

	Placemark = ParentXML->AddChild(L"Placemark");
	Child1 = Placemark->AddChild(L"name");
	Child1->SetText(PlacemarkName);
	Child1 = Placemark->AddChild(L"description");
	Child1->SetText(PlacemarkDescription);
	Child1 = Placemark->AddChild(L"style");
	Child2 = Child1->AddChild(L"LineStyle");
	Child3 = Child2->AddChild(L"color");
	Child3->SetText(L"ff0000ff");
	Child3 = Child2->AddChild(L"width");
	Child3->SetText(L"2");
	Child2 = Child1->AddChild(L"PolyStyle");
  Child3 = Child2->AddChild(L"color");
	Child3->SetText(L"000000ff");
	Child3 = Child2->AddChild(L"fill");
	Child3->SetText(L"1");
	Child1 = Placemark->AddChild(L"MultiGeometry");


	PolyCnt = Node->PolyIndex.get_length();
	LineCnt = Node->ContourIndex.get_length();
	PointCnt = Node->Coord.get_length();

	LineIndex = 0;
	for(i = 0; i < PolyCnt; i++)
	{
    Child2 = Child1->AddChild(L"Polygon");
		Child3 = Child2->AddChild(L"extrude");
		Child3->SetText(L"1");

		for(j = 0; j < Node->PolyIndex[i]; j++)
		{
			if(LineIndex + j >= LineCnt)
			{
				break;
			}

      if(j == 0) Child3 = Child2->AddChild(L"outerBoundaryIs");
			else Child3 = Child2->AddChild(L"innerBoundaryIs");
			Child4 = Child3->AddChild(L"LinearRing");
			Child5 = Child4->AddChild(L"coordinates");

			Str = "";
			for(k = 0; k < Node->ContourLength[LineIndex + j]; k++)
			{
				if(Node->ContourIndex[LineIndex + j] + k >= PointCnt)
				{
					break;
				}
				Str = Str + Node->Coord[Node->ContourIndex[LineIndex + j] + k];
			}
			Child5->SetText(Str);
		}
		LineIndex += Node->PolyIndex[i];
	}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::GenerateNames(TBoundaryTreeNode* Node)
{
	UnicodeString Name = Node->Text;
	switch(Node->AdminLevel)
	{
		
	}
	FolderName = Name;
	PlacemarkName = Name;
	PlacemarkDescription = "";
}
Планета при импорте кладет все полигоны в одну папку :lol:
Так что древовидная структура обломается.
Зато в других гис вполне может работать.
Последний раз редактировалось DJ VK 04 июл 2017, 16:18, всего редактировалось 1 раз.
Аватара пользователя
DJ VK
Гуру
Сообщения: 1468
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 80 раз
Поблагодарили: 314 раз

Re: Импорт Административно-территориального деления

Сообщение DJ VK »

Для импорта в планету воспользуемся форматом SML

Экспорт в SML

1. Экспорт.

Код: Выделить всё

        CatCnt = 1;
	RowCnt = 1;

	_di_IXMLNode Child1;
	_di_IXMLNode Child2;
	_di_IXMLNode Child3;

	_di_IXMLDocument XMLDocument = NewXMLDocument();
	XMLDocument->Active = True;
	XMLDocument->Encoding = "UTF-8";

	_di_IXMLNode RootElement = XMLDocument->AddChild(L"DATAPACKET");
	RootElement->SetAttribute(L"Version", L"2.0");
	Child1 = RootElement->AddChild(L"METADATA");
	Child2 = Child1->AddChild(L"FIELDS");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"id");
	Child3->SetAttribute(L"fieldtype", L"i4");
	Child3->SetAttribute(L"readonly", L"true");
	Child3->SetAttribute(L"SUBTYPE", L"Autoinc");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"name");
	Child3->SetAttribute(L"fieldtype", L"string");
	Child3->SetAttribute(L"WIDTH", L"255");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"descr");
	Child3->SetAttribute(L"fieldtype", L"bin.hex");
	Child3->SetAttribute(L"SUBTYPE", L"Text");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"scale1");
	Child3->SetAttribute(L"fieldtype", L"i4");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"scale2");
	Child3->SetAttribute(L"fieldtype", L"i4");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"lonlatarr");
	Child3->SetAttribute(L"fieldtype", L"bin.hex");
	Child3->SetAttribute(L"SUBTYPE", L"Binary");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"lonL");
	Child3->SetAttribute(L"fieldtype", L"r8");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"latT");
	Child3->SetAttribute(L"fieldtype", L"r8");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"lonR");
	Child3->SetAttribute(L"fieldtype", L"r8");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"latB");
	Child3->SetAttribute(L"fieldtype", L"r8");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"color1");
	Child3->SetAttribute(L"fieldtype", L"i4");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"color2");
	Child3->SetAttribute(L"fieldtype", L"i4");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"visible");
	Child3->SetAttribute(L"fieldtype", L"boolean");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"picname");
	Child3->SetAttribute(L"fieldtype", L"string");
	Child3->SetAttribute(L"WIDTH", L"255");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"categoryid");
	Child3->SetAttribute(L"fieldtype", L"i4");
	Child2 = Child1->AddChild(L"PARAMS");
	Child2->SetAttribute(L"AUTOINCVALUE", L"1");
	RootElement = RootElement->AddChild(L"ROWDATA");

	_di_IXMLDocument XML2Document = NewXMLDocument();
	XML2Document->Active = True;
	XML2Document->Encoding = "UTF-8";

	_di_IXMLNode Root2Element = XML2Document->AddChild(L"DATAPACKET");
	Root2Element->SetAttribute(L"Version", L"2.0");
	Child1 = Root2Element->AddChild(L"METADATA");
	Child2 = Child1->AddChild(L"FIELDS");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"id");
	Child3->SetAttribute(L"fieldtype", L"i4");
	Child3->SetAttribute(L"readonly", L"true");
	Child3->SetAttribute(L"SUBTYPE", L"Autoinc");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"name");
	Child3->SetAttribute(L"fieldtype", L"string");
	Child3->SetAttribute(L"WIDTH", L"255");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"visible");
	Child3->SetAttribute(L"fieldtype", L"boolean");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"AfterScale");
	Child3->SetAttribute(L"fieldtype", L"i2");
	Child3 = Child2->AddChild(L"FIELD");
	Child3->SetAttribute(L"attrname", L"BeforeScale");
	Child3->SetAttribute(L"fieldtype", L"i2");
	Child2 = Child1->AddChild(L"PARAMS");
	Child2->SetAttribute(L"AUTOINCVALUE", L"1");
	Root2Element = Root2Element->AddChild(L"ROWDATA");

	AddSMLNode(RootElement, Root2Element, (TBoundaryTreeNode*)TV->Items->Item[0], "", 0);

	XMLDocument->SaveToFile(Edit1->Text +"Output.SML");
	XMLDocument = NULL;

	XML2Document->SaveToFile(Edit1->Text +"CategoryOutput.SML");
	XML2Document = NULL;

	Beep();
2. Процедуры

Код: Выделить всё

//---------------------------------------------------------------------------
void __fastcall TForm1::GenerateNames(TBoundaryTreeNode* Node)
{
	UnicodeString Name = Node->Text;
	switch(Node->AdminLevel)
	{
		
	}
	FolderName = Name;
	PlacemarkName = Name;
	PlacemarkDescription = "";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::AddSMLNode(_di_IXMLNode ParentXML, _di_IXMLNode CatXML, TBoundaryTreeNode* Node,
																		UnicodeString ParentFolder, int ParentFolderNum)
{
	int i;  //int i,j,k,l;
	TBoundaryTreeNode* ChildNode;
	UnicodeString FullFolderName;
	int FolderNum;
	GenerateNames(Node);

	if(Node->Count > 0)
	{
		if(ParentFolder != "") FullFolderName = ParentFolder + "\\" + FolderName;
		else FullFolderName = FolderName;
		FolderNum = AddSMLFolder(CatXML, FullFolderName);
	}
	else
	{
		FullFolderName = ParentFolder;
		FolderNum = ParentFolderNum;
	}

	if(Node->PolyIndex.get_length() > 0) AddSMLPlacemark(ParentXML, Node, FolderNum);

  ProgressBar1->Position--;

	if(Node->Count > 0)
	{
		for(i = 0; i < Node->Count; i++)
		{
			ChildNode = (TBoundaryTreeNode*)Node->Item[i];
			AddSMLNode(ParentXML, CatXML, ChildNode, FullFolderName, FolderNum);
		}
  }

}
//---------------------------------------------------------------------------
int __fastcall TForm1::AddSMLFolder(_di_IXMLNode ParentXML, UnicodeString FolderN)
{
	int Num = CatCnt;
	CatCnt++;
	_di_IXMLNode Folder = ParentXML->AddChild(L"ROW");
	Folder->SetAttribute(L"id", IntToStr(Num));
	Folder->SetAttribute(L"name", FolderN);
	Folder->SetAttribute(L"visible", L"TRUE");
	Folder->SetAttribute(L"AfterScale", L"3");
	Folder->SetAttribute(L"BeforeScale", L"23");
	return Num;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::AddSMLPlacemark(_di_IXMLNode ParentXML, TBoundaryTreeNode* Node, int CatID)
{
	int Num = RowCnt;
	Extended L = NaN;
	Extended R = NaN;
	Extended T = NaN;
	Extended B = NaN;

  RowCnt++;
	_di_IXMLNode Placemark = ParentXML->AddChild(L"ROW");
	Placemark->SetAttribute(L"id", IntToStr(Num));
	Placemark->SetAttribute(L"name", PlacemarkName);
	Placemark->SetAttribute(L"descr", PlacemarkDescription);
	Placemark->SetAttribute(L"scale1", L"2");
	Placemark->SetAttribute(L"scale2", L"0");

	Placemark->SetAttribute(L"scale1", L"2");
	Placemark->SetAttribute(L"scale2", L"0");

	Placemark->SetAttribute(L"color1", L"-65536");
	Placemark->SetAttribute(L"color2", L"16777215");
	Placemark->SetAttribute(L"visible", L"TRUE");
	Placemark->SetAttribute(L"picname", L"");
	Placemark->SetAttribute(L"categoryid", IntToStr(CatID));

	int i,j,k;
	int LineIndex, PolyCnt, LineCnt, PointCnt;

	ExPoint P;
	TIdEncoderMIME* MIMEEncoder = new TIdEncoderMIME(NULL);
	TMemoryStream* Stream = new TMemoryStream;

  PolyCnt = Node->PolyIndex.get_length();
	LineCnt = Node->ContourIndex.get_length();
	PointCnt = Node->XCoord.get_length();

	LineIndex = 0;
	for(i = 0; i < PolyCnt; i++)
	{
		if(i > 0)
		{
			P.X = NaN;
			P.Y = NaN;
			P.R = 0;
			Stream->Write(&P, sizeof(P));
		}
		for(j = 0; j < Node->PolyIndex[i]; j++)
		{
			if(LineIndex + j >= LineCnt)
			{
				break;
			}
			if(j > 0)
			{
				P.X = NaN;
				P.Y = -1;
				P.R = 0;
				Stream->Write(&P, sizeof(P));
			}
			for(k = 0; k < Node->ContourLength[LineIndex + j]; k++)
			{
				if(Node->ContourIndex[LineIndex + j] + k >= PointCnt)
				{
					break;
				}
				P.X = Node->XCoord[Node->ContourIndex[LineIndex + j] + k];
				P.Y = Node->YCoord[Node->ContourIndex[LineIndex + j] + k];
				P.R = 0;
				if(IsNan(L)) L = P.X;
				else if(L > P.X) L = P.X;
				if(IsNan(R)) R = P.X;
				else if(R < P.X) R = P.X;
				if(IsNan(T)) T = P.Y;
				else if(T < P.Y) T = P.Y;
				if(IsNan(B)) B = P.Y;
				else if(B > P.Y) B = P.Y;
				Stream->Write(&P, sizeof(P));
			}
		}
		LineIndex += Node->PolyIndex[i];
	}

	Stream->Position = 0;
	UnicodeString Str = MIMEEncoder->EncodeStream(Stream);
	delete Stream;
	delete MIMEEncoder;

	Placemark->SetAttribute(L"lonlatarr", Str);
	Placemark->SetAttribute(L"lonL", FloatToStrF(L, ffFixed, 10, 7));
	Placemark->SetAttribute(L"latT", FloatToStrF(T, ffFixed, 10, 7));
	Placemark->SetAttribute(L"lonR", FloatToStrF(R, ffFixed, 10, 7));
	Placemark->SetAttribute(L"latB", FloatToStrF(B, ffFixed, 10, 7));
}
Аватара пользователя
DJ VK
Гуру
Сообщения: 1468
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 80 раз
Поблагодарили: 314 раз

Re: Импорт Административно-территориального деления

Сообщение DJ VK »

Бонусы

1. БД, полученная в результате обработки (необработанный SML).
OSM Границы РФ. 17853 административных объекта 2-9 уровней. 305 МБ.
Границы населенных пунктов (около 5000) отброшены, уж больно их мало в масштабах страны.
https://cloud.mail.ru/public/EtJi/6aaV367R3

2. Исходный код для сборки в Rad studio XE10 (без проекта)
Вложения
Boundaries API.rar
(5.08 КБ) 388 скачиваний
Аватара пользователя
garl
Гуру
Сообщения: 1625
Зарегистрирован: 16 июл 2008, 14:40
Откуда: Краснодар, Кубанская столица.
Благодарил (а): 97 раз
Поблагодарили: 272 раза

Re: Импорт Административно-территориального деления

Сообщение garl »

ну а зажать всё в архив если?
зачем тянуть 305Мб если можно совсем чуток вытянуть....
Russian NDN Team
QIP NightlyTester
Аватара пользователя
DJ VK
Гуру
Сообщения: 1468
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 80 раз
Поблагодарили: 314 раз

Re: Импорт Административно-территориального деления

Сообщение DJ VK »

Добавлен архив. 62 МБ.
Аватара пользователя
garl
Гуру
Сообщения: 1625
Зарегистрирован: 16 июл 2008, 14:40
Откуда: Краснодар, Кубанская столица.
Благодарил (а): 97 раз
Поблагодарили: 272 раза

Re: Импорт Административно-территориального деления

Сообщение garl »

учить и учить ;)
sml - 36,7Мб
sql - 28.4 Мб
https://cloud.mail.ru/public/Hn4n/f9YqPYuTE

я такое вытаскивал экспортом из конвертированных карт OSM.
может можно и через overpass api сделать ...
Russian NDN Team
QIP NightlyTester
Аватара пользователя
DJ VK
Гуру
Сообщения: 1468
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 80 раз
Поблагодарили: 314 раз

Re: Импорт Административно-территориального деления

Сообщение DJ VK »

кстати мультиполигоны превратились в мультипути.
ёклмн, что ж это за метод такой детектирования мультиполигона по одинаковым первой и последней точке?? На то он и мультиполигон, что они разные, ибо это два разных полигона.
имхо, косяк в SML.

P/s в перспективе
-добавить к noname нодам номера id
-переделать базу с мультиполигонами
-всё будет разложено на несколько разных уровней, дабы поддержать быстрое включение-выключение слоев: ФО / ОБЛ / (Районы+ГО) / Поселения
-будут раскрашены разные уровни в разные цвета с разной толщиной линии
Аватара пользователя
garl
Гуру
Сообщения: 1625
Зарегистрирован: 16 июл 2008, 14:40
Откуда: Краснодар, Кубанская столица.
Благодарил (а): 97 раз
Поблагодарили: 272 раза

Re: Импорт Административно-территориального деления

Сообщение garl »

на счёт разных цветом думал, но что делать с границами? она ж единая будет для разных цветов...
Russian NDN Team
QIP NightlyTester
Аватара пользователя
DJ VK
Гуру
Сообщения: 1468
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 80 раз
Поблагодарили: 314 раз

Re: Импорт Административно-территориального деления

Сообщение DJ VK »

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

Вернуться в «SAS.Планета»