На главную... Продукты | Технологии | Классификаторы | Проекты | Скачать | Цены| Форум | Статьи | Обучение | Контакты

[MATHAPI] Функция mathSheetFromFrame - странное поведение

Поиск  Пользователи  Правила  Войти
Форум » Linux » Средства разработки ГИС-приложений для Linux
Страницы: 1
RSS
[MATHAPI] Функция mathSheetFromFrame - странное поведение, Функция mathSheetFromFrame - странное поведение
 
Здравствуйте.
Пишу утилиту для импорта SXF (полученных из OpenStreet Map проекта, доступных для скачивания с Вашего сайта)
Алгоритм пока следующий:
  1. Получить габариты карты SXF.
  2. Вычислить список листов MAP карты в требуемой мне системе
  3. ...
  4. ...
  5. ...
  6. Запустить процесс конвертирования SXF в MAP
Сейчас на этапе вычисления списка листов столкнулся с следующим поведением функции mathSheetFromFrame  из mathapi:
Код
// Создание списка номенклатур по заданным габаритам района
// hmap - идентификатор открытых данных
// info  - заданная область расчёта номенклатур листов карты (метрика
//                                              должна быть замкнутой)
// scale - знаменатель масштаба карты (25000 - 1000000)
// listreg - адрес массива структур паспортных данных листа карты
// sheet - максимальное число номенклатур
// Возвращаемое значение: при ошибке - 0,
// при нормальном завершении заполнятся поля структуры LISTREGISTER для
// каждого листа

long int WINAPI  mathSheetFromFrame(HMAP  hmap, HOBJ info, long scale,
                                    LISTREGISTER* listreg,
                                    long sheet);
Карта масштаба 25000 (карта Рязанской области с сайта)
Подаю на вход временно созданную карту, объект с замкнутой метрикой, соответствующей габаритам SXF карты,
и массив из 1024 структур LISTREGISTER.

На моём хосте (ПК) с использованием ГИС Конструктор с сайта работает корректно (правда масштаб приходится менять  на 100000 из-за ограничений FREE версии),
получаю рассчитанные 72 листа карты.
На целевой платформе (arm) в масштабе 25000 должно быть 858 листов рассчитано,
и вроде бы данное количество листов влезает в массив из 1024 структур,
но функция mathSheetFromFrame возвращает 1024, и массив структур никак не заполняет.


А вот если создать массив из 2048 элементов, то функция mathSheetFromFrame уже нормально работает,рассчитывая 858 листов карты.Готового примера у меня нет, приведу пока только функцию, вычисляющую список листов:
Код
LISTREGISTER* calcSheets(const QFileInfo& sxfFile, const QFileInfo& rscFile)
{
    QString sxfFilePath = sxfFile.absoluteFilePath();
    QByteArray sxfKoi8r = gis::common::convertStringToKOI8_R(sxfFilePath);
    QByteArray rscKoi8r = gis::common::convertStringToKOI8_R(rscFile.absoluteFilePath());
    gis::core::MapInfo mapInfo;
    gis::core::VMapSheetInfo sheetInfo;
    long rc = panorama::mapGetAnySxfInfoByName(sxfKoi8r.constData(), mapInfo, sheetInfo);
    if (rc == 0){
        qDebug() << "can't get sxf info for" << sxfFile.absoluteFilePath();
        return nullptr;
    }
    system("mkdir /tmp/mapForSheets");
    HMAP hmap = panorama::mapCreateMapEx("/tmp/mapForSheets/map", rscKoi8r.constData(), mapInfo, sheetInfo);
    if (hmap == 0){
        qDebug() << "can't create map";
        return nullptr;
    }
    HOBJ hobj = mapCreateObject(hmap);
    if (hobj == 0){
        qDebug() << "can't create map obj";
        mapCloseData(hmap);
        return nullptr;
    }
    gis::coord::System s(mapInfo.getEPSGCode());
    gis::coord::GeoCoord sxfNW(s, sheetInfo.getGeoNorthWest().getB(), sheetInfo.getGeoNorthWest().getL());
    gis::coord::GeoCoord sxfNE(s, sheetInfo.getGeoNorthEast().getB(), sheetInfo.getGeoNorthEast().getL());
    gis::coord::GeoCoord sxfSE(s, sheetInfo.getGeoSouthEast().getB(), sheetInfo.getGeoSouthEast().getL());
    gis::coord::GeoCoord sxfSW(s, sheetInfo.getGeoSouthWest().getB(), sheetInfo.getGeoSouthWest().getL());

    rc = mapAppendPointGeo(hobj, sxfNW.getB(), sxfNW.getL());
    if (rc == 0){
        qDebug() << "can't add point to object";
        mapFreeObject(hobj);
        mapCloseData(hmap);
        return nullptr;
    }
    rc = mapAppendPointGeo(hobj, sxfNE.getB(), sxfNE.getL());
    if (rc == 0){
        qDebug() << "can't add point to object";
        mapFreeObject(hobj);
        mapCloseData(hmap);
        return nullptr;
    }
    rc = mapAppendPointGeo(hobj, sxfSE.getB(), sxfSE.getL());
    if (rc == 0){
        qDebug() << "can't add point to object";
        mapFreeObject(hobj);
        mapCloseData(hmap);
        return nullptr;
    }
    rc = mapAppendPointGeo(hobj, sxfSW.getB(), sxfSW.getL());
    if (rc == 0){
        qDebug() << "can't add point to object";
        mapFreeObject(hobj);
        mapCloseData(hmap);
        return nullptr;
    }
    rc = mapAppendPointGeo(hobj, sxfNW.getB(), sxfNW.getL());
    if (rc == 0){
        qDebug() << "can't add point to object";
        mapFreeObject(hobj);
        mapCloseData(hmap);
        return nullptr;
    }
    const int MaxSheetsCount = 1024*2;
    LISTREGISTER* lists = new LISTREGISTER[MaxSheetsCount];
    rc = mathSheetFromFrame(hmap, hobj, mapInfo.getScale(), lists, MaxSheetsCount);
    if (rc == 0){
        qDebug() << "can't calc sheets";
        mapFreeObject(hobj);
        mapCloseData(hmap);
        return nullptr;
    }else{
        qDebug() << "rc of calc sheets" << rc;
    }
    for (long i = 0; i < rc; i++){
        gis::core::VMapSheetInfo sheet(lists[i]);
        qDebug() << gis::common::parseStringFromKOI8_R(lists[i].Nomenclature) << lists[i].Length;
        qDebug() << sheet.getNomenclature() << sheet.getName() << sheet.getPlaneNorthEast().qPoint() << sheet.getPlaneSouthWest().qPoint();
    }
    mapFreeObject(hobj);
    mapCloseData(hmap);
    return lists;
}
Так работает (массив из 2048 элементов), листы рассчитываются:
Цитата
Запускается ./run.sh...
SxfUtil
mkdir:
cannot create directory '/tmp/mapForSheets'
: File exists
rc of calc sheets 858
"0.N-37-102-1-2" 544
"0.N-37-102-1-2" "N3710212" QPointF(5.91185e+06,7.48334e+06) QPointF(5.90261e+06,7.47497e+06)
"0.N-37-102-2-1" 544
"0.N-37-102-2-1" "N3710221" QPointF(5.91183e+06,7.49167e+06) QPointF(5.90258e+06,7.48331e+06)
"0.N-37-102-2-2" 544
"0.N-37-102-2-2" "N3710222" QPointF(5.91182e+06,7.5e+06) QPointF(5.90255e+06,7.49166e+06)
"0.N-37-103-1-1" 544
"0.N-37-103-1-1" "N3710311" QPointF(5.91183e+06,7.50833e+06) QPointF(5.90255e+06,7.5e+06)
"0.N-37-103-1-2" 544
...
...
...
"0.N-38-014-3-4" 544
"0.N-38-014-3-4" "N3801434" QPointF(6.14603e+06,8.35752e+06) QPointF(6.13702e+06,8.34929e+06)
Приложение завершилось с кодом 0.
А если массив из 1024 элементов, то листы уже не рассчитываются:
Цитата
Запускается ./run.sh...
SxfUtil
mkdir:
cannot create directory '/tmp/mapForSheets'
: File exists
rc of calc sheets 1024
"" 0
"" "" QPointF(0,0) QPointF(0,0)
"" 0
"" "" QPointF(0,0) QPointF(0,0)
"" 0
"" "" QPointF(0,0) QPointF(0,0)
"" 0
"" "" QPointF(0,0) QPointF(0,0)
"" 0
...
...
...
"" 0
"" "" QPointF(0,0) QPointF(0,0)
Приложение завершилось с кодом 0.
 
А ещё, если взять карту Подольска из примеров, и использовать её вместо sxf, то на выходе получается 4 листа карты, только один из которых бьётся с оригинальным, причём номенклатуры не совпадают:

Скрытый текст

То есть у карты Подольска номенклатура единственного листа указана как :
Цитата
Номенклатура: "0.N-45-015.A"
Название листа: "ПОДОЛЬСК"

А если по габаритам этого листа попросить рассчитать листы для масштаба 1:100000, то на выходе 4 листа, один из них полностью совпадает с оригинальным, только номенклатура у него уже другая :

Цитата
Номенклатура: "0.N-37-016"
Название листа: "N37016"
А три других листа своими гранями прилегают к оригинальному листу из карты (это я ещё могу понять).

Почему разные номенклатуры рассчитываются ?
 
Здравствуйте!

Привожу код функции mapSheetFromFrame, в которой производится расчет номенклатурных листов.
Функция немного модифицирована: теперь, если размера массива не хватает для заполнения всех номенклатурных листов, производится запись того числа, которое можно записать (изменение помечено комментарием 28/06/18):
Код
//================================================================
// Создание списка номенклатур по заданным габаритам
// hmap - идентификатор открытых данных
// object - заданная область расчёта номенклатур листов карты (метрика
//                                              должна быть замкнутой)
// scale - знаменатель масштаба карты (25000 - 1000000)
// listreg - адрес массива структур паспортных данных листа карты
// sheet - максимальное число номенклатур (12000)
// Возвращаемое значение: при ошибке - 0,
// при нормальном завершении заполнятся поля структуры LISTREGISTER для
// каждого листа
//================================================================
long int _export WINAPI mathSheetFromFrame(HMAP  hmap, HOBJ  object, long scale, LISTREGISTER* listreg,
                                           long sheet)
{
 if(!hmap || !object || !listreg || !sheet)    return 0;
 if(mapIsGeoSupported(hmap) == 0)  return 0;

 HOBJ  info = object;
 FRAME   frame;
 int regim = 0;

 if(mathCheckFrame(hmap, info, &frame, regim) == 0)
  return 0;

 double b1 = frame.X1/3600.0;
 double b2 = frame.X2/3600.0;
 double l1 = frame.Y1/3600.0;
 double l2 = frame.Y2/3600.0;

 double stepb = 1.0;
 double stepl = 1.0;

 switch(scale)
 {
   case  1000000:
               stepb = 4.0;
               stepl = 6.0;
               break;
   case  500000:
               stepb = 2.0;
               stepl = 3.0;
               break;
   case  200000:
               stepb = 4.0/6.0;
               stepl = 6.0/6.0;
               break;
   case  100000:
               stepb = 4.0/12.0;
               stepl = 6.0/12.0;
               break;
   case  50000:
               stepb = 4.0/24.0;
               stepl = 6.0/24.0;
               break;
   case  25000:
               stepb = 4.0/48.0;
               stepl = 6.0/48.0;
               break;
   case  10000:
               stepb = 4.0/96.0;
               stepl = 6.0/96.0;
               break;
   case  5000:
               stepb = 4.0/192.0;
               stepl = 6.0/192.0;
               break;
   default : return 0;
 }

 // Выделить память под массив номенклатур
 char* namearray = ::AllocateTheMemory(sheet*32);
 if (namearray == 0)
  return 0;
 memset(namearray, 0, sheet*32);

 double compA = 60.0;
 double compB = 76.0;
 int realcomp = 1;

 if((b1>=compA)||(b1<=-compA))realcomp = 2;  
 if((b1>=compB)||(b1<=-compB))
  {
   if(scale == 200000)realcomp = 3;
   else               realcomp = 4;
  }

 // Выравниваем на границу 1000000
 int number = (int)(b1/(4*realcomp));
 double b0 = (4*realcomp) * number;
 if (b0 > b1) b0-= stepb;

 number = (int)(l1/(6*realcomp));
 if (number < 0)   number--;
 
 double l0 = 6*realcomp*number;

 double bc1 = b0;

 int line = 0;
 double steplcomp = stepl;

 int countname = 0;
 while(bc1 < b2)
 {
  double bc2 = bc1 + stepb;
  double lc1 = l0;

  while(lc1 < l2)
  {
   steplcomp = stepl;

   int comp = 1;

   if(bc1 > 0 && (bc1 + bc2)/2. >= compA)           // север
    {
      comp = 2;                                     // сдвоенные
      steplcomp = stepl*2;
    }
   if(bc1 < 0 && (bc1+bc2)/2. <= compA*-1)          // юг
    {
      comp = 2;
      steplcomp = (int)(stepl*2. + 0.5);
    }
   if(bc1 > 0 && (bc1+bc2)/2 >= compB)             // крайний север
    {
      if(scale == 200000)
       {
         comp = 3;
         steplcomp = stepl*3;
       }
      else
       {
         comp = 4;
         steplcomp = (int)(stepl*4 + 0.5);
       }
    }
   if(bc1 < 0 && (bc1+bc2)/2.0 <= compB*-1)
    {
      if(scale == 200000)steplcomp = stepl*3;
      else               steplcomp = (int)(stepl*4 + 0.5);
    }

   double lc2 = lc1 + steplcomp;

   if (lc2 < l1)
    {
      lc1+=steplcomp;
      continue;
    }

   char sheetname[MAX_PATH];
   memset(sheetname, 0, sizeof(sheetname));

   int retcode = 0;

   retcode = mathSetSheetName(scale, (bc1 + bc2)/2., lc1+(lc2-lc1)/(2.*comp), comp, sheetname);

   if (retcode)
   {
     if (countname >= sheet)
     {

       if (mapIsMessageEnable())
       {
         const WCHAR * cap = _mathtxt(31);   // Создание списка номенклатур по заданным габаритам 
         const WCHAR * mess = _mathtxt(32);  // Число номенклатур больше допустимого

         MessageBoxW(0, mess, cap, MB_TASKMODAL | MB_OK | MB_ICONWARNING);
       }

       mathSetListRegister(namearray, listreg, scale, countname);                       // 28/06/18
       int countret = mathSetBelongNomenclature(hmap, info, listreg, countname);  

       if (namearray)
         ::FreeTheMemory(namearray);

       return countret;
     }

      memcpy(namearray + countname*32, sheetname, 32);
      countname++;
   }

   lc1+=steplcomp;
  }
  bc1+=stepb;
 }
 
 mathSetListRegister(namearray, listreg, scale, countname);
 int countret = mathSetBelongNomenclature(hmap, info, listreg, countname);   

 if (namearray)
  ::FreeTheMemory(namearray);

 return countret;
}
 
Ладно, вот ещё момент интересный.Есть у меня карта - векторная карт санкт-петербурга.
Когда пытаюсь рассчитывать номенклатуры по MAP файл и классификатору - получаю два листа, один полностью совпадающий с исходным листом векторной карты, второй видимо прилегающий к ней.Когда пытаюсь рассчитывать номенклатуры по SXF файлу, из которого была получена данная векторная карта, получаю 0 листов.Чтобы понять что происходится воспользовался листингом функции, приведённой выше, с добавленным туда дебажным выводом.
Результаты очень интересные.Сама функция:
Скрытый текст

Меня интересовало что происходит в самом конце с массивом рассчитанных LISTREGISTER после вызовы функции   mathSetBelongNomenclature(hmap, info, listreg, countname);
При работе с MAP картой получил следующий вывод:
Цитата
"0.O-36-133"
"0.O-36-121"
"0.O-36-109"
"0.O-36-097"
"0.O-36-085"
"0.O-36-073"
"0.O-36-061"
"0.O-36-049"
"0.O-36-037"
"0.O-36-025"
"0.O-36-013"
"0.O-36-001"
mathMySheetFromFrame after Belong countret: 2
"0.O-36-013"
"0.O-36-001"
""
""
""
""
""
""
""
""
""
""
mathMySheetFromFrame normal quit. countret: 2
rc of calc sheets 2

Видно, что функция mathSetBelongNomenclature(hmap, info, listreg, countname) модифицирует массив - перемещает элементы и очищает не нужные.
При работе с SXF получил следующее:


Цитата
"0.O-36-133"
"0.O-36-121"
"0.O-36-109"
"0.O-36-097"
"0.O-36-085"
"0.O-36-073"
"0.O-36-061"
"0.O-36-049"
"0.O-36-037"
"0.O-36-025"
"0.O-36-013"
"0.O-36-001"
mathMySheetFromFrame after Belong countret: 0
"0.O-36-001"
""
""
""
""
""
""
""
""
""
""
""
mathMySheetFromFrame normal quit. countret: 0
can't calc sheets

То есть функция отбраковала все листы, но в массиве почему-то остался один элемент с подходящим листом.
 
А, ну и до меня дошло почему при 1024 не рассчитывались листы.
Потому-что листов на самом деле было рассчитано 1353, а вот после отбраковки было оставлено 858. 1353 в 1024 конечно не влезали.
Страницы: 1
Читают тему (гостей: 1)



© КБ Панорама, 1991-2024

Регистрируясь или авторизуясь на форуме, Вы соглашаетесь с Политикой конфиденциальности