SASGIS

Веб-картография и навигация

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

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

Модератор: Tolik

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

Сообщение DJ VK » 04 июл 2017, 15:49

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

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

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

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 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 323 раз.

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

Сообщение DJ VK » 04 июл 2017, 15:50

Экспорт в 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 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 323 раз.

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

Сообщение DJ VK » 04 июл 2017, 15:57

Для импорта в планету воспользуемся форматом 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 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 323 раз.

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

Сообщение DJ VK » 04 июл 2017, 16:42

Бонусы

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

2. Исходный код для сборки в Rad studio XE10 (без проекта)
Вложения
Boundaries API.rar
(5.08 KiB) Скачиваний: 259

За это сообщение автора DJ VK поблагодарили: 2
garl (04 июл 2017, 18:33) • Tolik (04 июл 2017, 23:29)
Рейтинг: 10.53%
 
Аватара пользователя
DJ VK
Гуру
 
Сообщения: 1468
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 323 раз.

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

Сообщение garl » 04 июл 2017, 18:33

ну а зажать всё в архив если?
зачем тянуть 305Мб если можно совсем чуток вытянуть....
Russian NDN Team
QIP NightlyTester
Аватара пользователя
garl
Гуру
 
Сообщения: 1625
Зарегистрирован: 16 июл 2008, 14:40
Откуда: Краснодар, Кубанская столица.
Благодарил (а): 97 раз.
Поблагодарили: 273 раз.

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

Сообщение DJ VK » 04 июл 2017, 18:37

Добавлен архив. 62 МБ.

За это сообщение автора DJ VK поблагодарил:
garl (04 июл 2017, 22:57)
Рейтинг: 5.26%
 
Аватара пользователя
DJ VK
Гуру
 
Сообщения: 1468
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 323 раз.

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

Сообщение garl » 04 июл 2017, 23:17

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

я такое вытаскивал экспортом из конвертированных карт OSM.
может можно и через overpass api сделать ...
Russian NDN Team
QIP NightlyTester

За это сообщение автора garl поблагодарил:
Tolik (04 июл 2017, 23:29)
Рейтинг: 5.26%
 
Аватара пользователя
garl
Гуру
 
Сообщения: 1625
Зарегистрирован: 16 июл 2008, 14:40
Откуда: Краснодар, Кубанская столица.
Благодарил (а): 97 раз.
Поблагодарили: 273 раз.

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

Сообщение DJ VK » 05 июл 2017, 02:13

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

P/s в перспективе
-добавить к noname нодам номера id
-переделать базу с мультиполигонами
-всё будет разложено на несколько разных уровней, дабы поддержать быстрое включение-выключение слоев: ФО / ОБЛ / (Районы+ГО) / Поселения
-будут раскрашены разные уровни в разные цвета с разной толщиной линии
Аватара пользователя
DJ VK
Гуру
 
Сообщения: 1468
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 323 раз.

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

Сообщение garl » 05 июл 2017, 09:31

на счёт разных цветом думал, но что делать с границами? она ж единая будет для разных цветов...
Russian NDN Team
QIP NightlyTester
Аватара пользователя
garl
Гуру
 
Сообщения: 1625
Зарегистрирован: 16 июл 2008, 14:40
Откуда: Краснодар, Кубанская столица.
Благодарил (а): 97 раз.
Поблагодарили: 273 раз.

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

Сообщение DJ VK » 05 июл 2017, 13:19

garl писал(а):на счёт разных цветом думал, но что делать с границами? она ж единая будет для разных цветов...

поиграйся толщиной (уменьшая ее у вложенных объектов), и полупрозрачностью.
bound.jpg
Аватара пользователя
DJ VK
Гуру
 
Сообщения: 1468
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 323 раз.

След.

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

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10