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

Александр (Все сообщения пользователя)

Поиск  Пользователи  Правила  Войти
Форум » Пользователи » Александр
Выбрать дату в календареВыбрать дату в календаре

Страницы: 1 2 След.
Параллельное считываение рельефа, mapGetHeightValue, mapGetHeightArray, QThread
 
Добрый день.

Мы используем Gis Designer версии 11.10.7 под Astra Linux SE 1.4. Среда разработки Qt Creator.
Столкнулись со следующей проблемой. При использовании функций mapGetHeightValue или mapGetHeightArray в не основном потоке часто происходит зависание
потока, либо в последствии возникают наведенные ошибки (Вроде повисания процесса отрисовки карты). При чтении рельефа мы используем мьютексы.
Причем, если теже самые действия выполнять в основном потоке (Где отрисовывается GUI-интерфейс), то все нормально.

Урезали нашу задачу до маленького примера, где подобные глюки возникают всегда, даже если все выполнять все в одном, но не основном потоке. Карта масштаба 1 : 50000 и состоит из 350 листов.
Матрица высот расчитана с дискретом в 50 м. Если не вызыватть функцию mapGetHeightValue, то глюки пропадают.
В связи с этим вопрос: Как осуществлять параллельное считывание рельефа? Поддерживает ли функция mapGetHeightArray работу в множестве потоков?

Прилагаю пример кода:

Заголовочный файл calcMap.h:
[CODE]#include <QApplication>
#include <QVector>
#include <QList>
#include <QRunnable>
#include <QThread>
#include <QMutex>
#include <ma th.h>

#include <QDebug>

#ifndef MAP_API_H
#include <mapapi.h>
#endif

using namespace std;

class informVyr {
private:

public:
   informVyr() {}
   ~informVyr() {}

   QMutex *hMut_ptr;

   QString pathToMap;
   HMAP hmap;

   double Xstart; // Координаты начала матрицы
   double Ystart;
   double dsk; // дискрет

   QVector <QVector <double> > masIfo;

   void testVyr(int numL, int kolL);
};

// Класс расчета
class calcMap {
private:

public:
   calcMap(QString Mappath);
   ~calcMap();

   informVyr MIV;
};

// Класс параллельной обработки
class parInf : public QThread {
private:
   informVyr *MIV;
   int numL; // Номер среза
   int kolL; // кол-во срезов

public:
   parInf(informVyr *MIV, int numL, int kolL);
   void run();
};[/CODE]

Файл calcMap.cpp:
[CODE]#include "calcMap.h"

calcMap::calcMap(QString Mappath) {

   QMutex infMut;

   MIV.hMut_ptr = &infMut;
   MIV.pathToMap = Mappath; // Путь к карте
   MIV.hmap = mapOpenMap(Mappath.toStdString().c_str(), GENERIC_READ);
   if (!MIV.hmap)
       return;

   // Путь к матрице высот (Должна лежать в каталоге с картой и иметь такое же имя)
   string pathMtw = Mappath.toStdString();
   pathMtw =  pathMtw.substr(0, pathMtw.length()-4);
   pathMtw += ".mtw";

   qDebug() << "\nПодключение матрицы высот";
   if (!mapOpenMtrForMap( MIV.hmap, pathMtw.c_str(), GENERIC_READ))
       return;

   double dsk = 4000; // Дискрет

   // Расчет кол-ва элементов матрицы
   int cou = mapGetMtrCount(MIV.hmap);
   MTRDESCRIBE desc;
   mapGetMtrDescribe(MIV.hmap, 1, &desc);

   // Граничные точки матрицы
   double X1 = desc.FrameMeters.X1;
   double Y1 = desc.FrameMeters.Y1;
   double X2 = desc.FrameMeters.X2;
   double Y2 = desc.FrameMeters.Y2;

   for (int i = 2; i <= cou; i++) {
       mapGetMtrDescribe(MIV.hmap, i, &desc);

       if (desc.FrameMeters.X1 < X1)
           X1 = desc.FrameMeters.X1;
       if (desc.FrameMeters.Y1 < Y1)
           Y1 = desc.FrameMeters.Y1;

       if (desc.FrameMeters.X2 > X2)
           X2 = desc.FrameMeters.X2;
       if (desc.FrameMeters.Y2 > Y2)
           Y2 = desc.FrameMeters.Y2;

   }

   int xCou = ceil((X2 - X1)/dsk);
   int yCou = ceil((Y2 - Y1)/dsk);
   X2 = X1 + xCou*dsk;
   Y2 = Y1 + yCou*dsk;

   qDebug() << "\nМатрица:" << xCou << yCou;

   // Формирование матрицы
   MIV.masIfo.clear();
   MIV.masIfo.resize(xCou);

   for (int i=0 ; i < xCou; i++) {
       MIV.masIfo[i].resize(yCou);
       for (int j=0; j < yCou; j++)
           MIV.masIfo[i][j] = 0; // Зануление
   }

   // Инициализация параметров
   MIV.Xstart = X1;
   MIV.Ystart = Y1;
   MIV.dsk = dsk;

   int kolL = QThread::idealThreadCount(); // Кол-во параллельных процессов
   if (kolL < 1)
       kolL = 1;

   bool ParalPro = true; // Признак распараллеливания
   kolL = 1;             // Принудительная установка 1 потока

   qDebug() << "Кол-во процессов" << kolL;

   if (!ParalPro) {
       qDebug() << "\nПоследовательный расчет";

       for (int i = 0; i < kolL; i++)
           MIV.testVyr(i, kolL);

   } else {
       qDebug() << "\nПараллельный расчет по линиям";

       // Массив обрабатывющих потоков
       QVector <parInf*> masThread;
       masThread.resize(kolL);

       // Создание потоков
       for (int i = 0; i < kolL; i++)
           masThread[i] = new parInf(&MIV, i, kolL);

       // Запуск потоков
       for (int i = 0; i < kolL; i++)
           masThread[i]->start();

       int activeTCou = kolL;

       // Ожидание завершения всех потоков
       while (activeTCou > 0) {

          activeTCou = 0;
          for (int i = 0; i < kolL; i++) // Подсчет текущих потоков
              if (masThread[i]->isRunning())
                 activeTCou++;
       }

       // Удаление потоков
       for (int i = 0; i < kolL; i++) {
           delete masThread[i];
       }

   }

   mapCloseMap(MIV.hmap); // Закрытие карты

   return;
}

calcMap::~calcMap() { }

// Распараллеливание
parInf::parInf(informVyr *MIV, int numL, int kolL) : QThread() {
   this->MIV = MIV;
   this->numL = numL;
   this->kolL = kolL;;
}

void parInf::run() {
   MIV->testVyr(numL, kolL);
}

void informVyr::testVyr(int numL, int kolL) {
   qDebug() << "\nНачало расчета среза линий №" << numL;

   int begL = 0;
   int endL = masIfo.size();

   if (numL != -1) { // Если задан номер среза
       begL = numL*masIfo.size()/kolL;
       endL = (numL+1)*masIfo.size()/kolL;

       if (numL == kolL-1) // Если срез последний
          endL = masIfo.size(); // Конец массива
   }

   qDebug() << "От" << begL << " До" << endL;

   for (int i = begL; i < endL; i++) {
       if (i%5 == 0)
           qDebug() << "i = " << i;

       for (int j = 0; j < masIfo[i].size(); j++) {
           hMut_ptr->lock();
           mapGetHeightValue(hmap, Xstart + dsk*i, Ystart + dsk*j);
           hMut_ptr->unlock();
       }
   }

   qDebug() << "\nКонец расчета среза линий" << numL;

   return;
}[/CODE]
Пересборка карты глобуса
 
Добрый день!

У нас есть используется карта глобуса в проекции Меркатора с границами от -20 градусов до 340 градусов. У нас возникла необходимость в изменении данной карты.
Нам бы хотелось скопировать листы так, что бы формат карты стал от -180 до 360 градусов, либо сделать вторую карту формата -180 - 180 градусов.
Листов SXF у нас нет, есть только собранная карта. В связи с этим вопросы:
1) Как нам скопировать листы так, что бы при сборке они сшивались слева, а не справа?
2) Как нам изменять центральную ось карты?

Мы пробовали выгружать карту в SXF и формировать файл dir так, что бы первым шел лист гринвического мередиана, но карта все равно собиралась такой же (формат -20 -340).
[IMG]https://ibb.co/P59JfVQ[/IMG]
https://ibb.co/P59JfVQ

[IMG]https://ibb.co/3M3Y806[/IMG]
https://ibb.co/3M3Y806
Проблема с открытием больших карт, GisDesigner, limits.conf
 
[CODE]HMAP mapHandle = mapOpenData(“/tmp/testmap/20t.map”);
qDebug()  << mapGetListCount(mapHandle);[/CODE]

Открывает карту как состоящую из одного листа. Создает 2 файла в каталоге LOG:
map.map.LOG, map.map.TAC

map.map.LOG содержит:
---> 10:27:52 КАРТА ОТКРЫТА. 12/10/2020  
    10:27:52 КАРТА ЗАКРЫТА.12/10/2020  

map.map.TAC содержит:
TAK
Изменено: Александр - 12.10.2020 10:37:39
Проблема с открытием больших карт, GisDesigner, limits.conf
 
[QUOTE]Елена Кузнецова написал:
[QUOTE][URL=/forum/user/16304/]Александр[/URL] написал:
Мы используем gisdesigner 11.10.4 под Astra Linux 1.4 для разработки ПО. Карты собираем в ГИС Оператор версии 11.13.3. Карта из 30000 НЛ в нем нормально собирается и открывается. Матрица высот рассчитывается и подцепляется.А вот в нашем ПО карта открывается, но только в виде одного номенклатурного листа. Пробовали разные функции(mapOpenMap, mapOpenData,mapOpenMapUn, mapOpenDataUn и т.д.). Результат одинаковый. Функция mapGetListCount выдает значение в 1 лист.[/QUOTE] Выслали на адрес электронной почты дистрибутив программы.
ГИС Конструктор 11.10.7 Free (Qt4, 64 бит, ОС релиз Смоленск 1.4, 1.5)[/QUOTE]

Прошу прощение за перерыв в диалоге, так как некогда было заниматься данным воросом (Были другие более срочные задачи).
На почту мне ничего не приходило. Прошу выслать еще раз на artlesko90@mail.ru.
Проблема с открытием больших карт, GisDesigner, limits.conf
 
Команда выдала:
[CODE]Limit Soft Limit Hard Limit Units
Max cpu time              unlimited            unlimited            seconds
Max file size             unlimited            unlimited            bytes
Max data size             unlimited            unlimited            bytes
Max stack size            8388608              unlimited            bytes
Max core file size        0                    unlimited            bytes
Max resident set          unlimited            unlimited            bytes
Max processes             31000                32000                processes
Max open files            32048                34096                files
Max locked memory         65536                65536                bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks
Max pending signals       62777                62777                signals
Max msgqueue size         819200               819200               bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited            us[/CODE]
Проблема с открытием больших карт, GisDesigner, limits.conf
 
Добрый день!

Мы используем gisdesigner 11.10.4 под Astra Linux 1.4 для разработки ПО. Карты собираем в ГИС Оператор версии 11.13.3. Карта из 30000 НЛ в нем нормально собирается и открывается. Матрица высот рассчитывается и подцепляется.
А вот в нашем ПО карта открывается, но только в виде одного номенклатурного листа. Пробовали разные функции(mapOpenMap, mapOpenData,
mapOpenMapUn, mapOpenDataUn и т.д.). Результат одинаковый. Функция mapGetListCount выдает значение в 1 лист.

Карты примерно до 15000 листов открываются без проблем. Файл limits.conf настроен в соответствии с требованием к установке ГИС Оператор. Мы пробовали изменять кол-во файлов и процессов в limits.conf в сторону десятикратного увеличения, но это нам так же не помогло. Подскажите пожалуйста, в чем может быть проблема?

Значения из limits.conf:
*hard nofile 34096
*soft nofile 32048
*hard nproc 32000
*soft nproc 31000
root hard nofile 34096
root soft nofile 32048
root hard nproc 32000
root soft nproc 31000
Отклонения в плане и точность матрицы высот
 
Столкнулись с проблемой формирования новой матрицы. При создании матрицы через функцию mapCreateMtw и занесении в нее высот она не открывается в Гис Операторе (Ошибка сегментирования).
Даже если просто копировать все высоты, то возникает таже проблема, плюс матрица занимает в 2 раза больше места, чем исходная. Даже если не заполнять новую матрицу высотами, а оставить пустой, то она все равно не открывается.
Исходная карта и матрица высот открываются в Гис Операторе и нашем ПО (На основе гис дизайнер) без ошибок.

В пример участок кода по формированию матрицы (Astra Linux, Qt Creator):

// pathCat - Путь к каталогу с исходной картой
   qDebug() << "\nПерерасчет матрицы высот" << pathCat;

   QString pathMap = pathCat + "map.map";
   QString pathMtw = pathCat + "map.mtw";
   QString pathMtw_Ort = pathCat + "map_ort.mtw";

   // Создание бегунка
   QProgressDialog progress("", QString(), 0, 0, NULL);

   progress.setLabelText("Пересчет матрицы высот");
   progress.setMinimum(0);
   progress.setMaximum(100);
   progress.setWindowModality(Qt::WindowModal);
   progress.setWindowFlags(Qt::ToolTip);
   progress.setAutoClose(0);
   progress.setAutoReset(0);
   progress.setMinimumDuration(0);

   progress.setMinimumWidth(350);
   progress.setMaximumWidth(350);

   progress.setMinimumHeight(60);
   progress.setMaximumHeight(60);

   // окно в центр экрана
   QDesktopWidget desktop;
   QRect rect = desktop.availableGeometry(desktop.primaryScreen()); // прямоугольник с размерами экрана
   QPoint center = rect.center(); //координаты центра экрана
   center.setX(center.x() - (progress.width()/2));  // учитываем половину ширины окна
   center.setY(center.y() - (progress.height()/2));  // половину высоты

   progress.move(center);

   // Начальное значение
   progress.setValue(0);
   progress.show();
   QApplication::processEvents();
   SleepTheThread(1);


   qDebug() << "\nЗагрузка карты" << pathMap;

   HMAP hmap = mapOpenMap(pathMap.toStdString().c_str(), GENERIC_READ);

   if (!hmap) {

       qDebug() <<  ("Не удалось открыть карту " + pathMap.toStdString()).c_str();

       return;
   }

   progress.setValue(2);
   QApplication::processEvents();


   if (!QFile(pathMtw).exists()) {
       qDebug() << ("Не найдена матрица высот " + pathMtw.toStdString()).c_str();

       return;
   } else {

       qDebug() << "\nПодключение матрицы высот";

       if (mapOpenMtrForMap(hmap, pathMtw.toStdString().c_str(), GENERIC_READ) == 0) {
           qDebug() << ("Не удалось открыть матрицу высот " + pathMtw.toStdString()).c_str();

           return;
       }

   }

   progress.setValue(5);
   QApplication::processEvents();

   // Получение координат начала матрицы высот
   MTRDESCRIBE a;
   int c = mapGetMtrCount(hmap);
   mapGetMtrDescribe(hmap, c, &a);
   double X1 = a.FrameMeters.X1;
   double Y1 = a.FrameMeters.Y1;
   double X2 = a.FrameMeters.X2;
   double Y2 = a.FrameMeters.Y2;
   double dsk = a.ElementInPlane; // Дискрет в метрах

   // Получение информации по карте
   MAPREGISTEREX mapR;
   DATUMPARAM datP;
   ELLIPSOIDPARAM elP;

   mapGetDocProjection(hmap, &mapR,  &datP, &elP);

   // Удаление матрицы высот ортодромий если есть
   QFile(pathMtw_Ort).remove();

   // Формирование матрицы высот
   BUILDMTW mtrB;
   memset((char *)&mtrB, 0x00, sizeof(BUILDMTW));

   mtrB.StructSize = sizeof (mtrB);
   mtrB.NotCheckDiskFreeSpace = 0;
   mtrB.BeginX = X1;
   mtrB.BeginY = Y1;
   mtrB.Width =  Y2 - Y1;
   mtrB.Height =  X2 - X1;
   mtrB.ElemSizeMeters = dsk;
   mtrB.ElemSizeBytes = 8;
   mtrB.ReliefType = 0;
   mtrB.Unit = 0;
   mtrB.Scale = mapR.Scale;
   mtrB.HeightSuper = 1;
   mtrB.FastBuilding = 1;


   MTRPROJECTIONDATA mtrPD;
   memset((char *)&mtrPD, 0x00, sizeof(MTRPROJECTIONDATA));

   mtrPD.AxisMeridian = mapR.AxisMeridian;
   mtrPD.CoordinateSystem = mapR.CoordinateSystem;
   mtrPD.EllipsoideKind = mapR.EllipsoideKind;
   mtrPD.FalseEasting = mapR.FalseEasting;
   mtrPD.FalseNorthing = mapR.FalseNorthing;
   mtrPD.FirstMainParallel = mapR.FirstMainParallel;
   mtrPD.Free = 0;
   mtrPD.HeightSystem = mapR.HeightSystem;
   mtrPD.MainPointParallel = mapR.MainPointParallel;
   mtrPD.MapType = mapR.MapType;
   mtrPD.PoleLatitude = mapR.PoleLatitude;
   mtrPD.PoleLongitude = mapR.PoleLongitude;
   mtrPD.ProjectionType = mapR.MaterialProjection;
   mtrPD.ScaleFactor = mapR.ScaleFactor;
   mtrPD.SecondMainParallel = mapR.SecondMainParallel;
   mtrPD.StructSize = sizeof(mtrPD);
   mtrPD.TurnAngle = mapR.TurnAngle;
   mtrPD.ZoneIdent = mapR.ZoneIdent;
   mtrPD.ZoneNumber = mapR.ZoneNumber;


   int res = mapCreateMtw(pathMtw_Ort.toStdString().c_str(), &mtrB, &mtrPD);

   if (!res) {
       qDebug() << ("Не удалось создать матрицу высот " + pathMtw_Ort.toStdString()).c_str();

       return;
   }

   if (mapOpenMtrForMap(hmap, pathMtw_Ort.toStdString().c_str(), GENERIC_WRITE) == 0) {
       qDebug() << ("Не удалось открыть матрицу высот " + pathMtw_Ort.toStdString()).c_str();

       return;
   }

   long int hei = (X2 - X1) / dsk;
   long int wid = (Y2 - Y1) / dsk;

   qDebug() << "Проход по высотам в циклах" << hei << wid;

   for (int i = 0; i < hei; i++) {
       for (int j = 0; j < wid; j++) {
           // Получение рельефа
           double curH = mapGetHeightValueOfMtr(hmap, 1, X1 + i*dsk, Y1 + j*dsk);
 
           // Занесение рельефа
           mapPutHeightValue(hmap, 2, X1 + i*dsk, Y1 + j*dsk, curH);
       }

       if (hei%20) {
           progress.setValue(5 + i*95/hei);
           QApplication::processEvents();
       }

   }

   mapCloseMtr(hmap, 2);
   mapCloseMtr(hmap, 1);

   mapCloseMap(hmap);

   progress.setValue(100);
   QApplication::processEvents();
   SleepTheThread(1);
   progress.close();
Отклонения в плане и точность матрицы высот
 
Возможно, хватило бы наличия всего двух функций по типу mapGetHeightArray (Получение заданного кол-ва высот): на отрезке ортодромии и на отрезке локсодромии.
Отклонения в плане и точность матрицы высот
 
[QUOTE]Елена Кузнецова написал:
[QUOTE][URL=/forum/user/16304/]Александр[/URL] написал:
У нас возник вопрос увеличения точности при снятии вырезок рельефа с  матрицы высот. Мы строим прямоугольные вырезки рельефа по ортодромиям с заданной шириной.Если брать высоты в плане функцией mapGetHeightValue с заданным дискретом, то можно получить существенные  отклонения от реальных координат в центральной части ортодромии (До 350 м  при длине ортодромии 350 км), кроме того длина полученной вырезки рельефа так же отличается от длины ортодромии. Искажения особенно сильно заметны при  переходе между разными зонами карты. Мы помним про ваши рекомендации не  собирать карты с большим числом зон, однако в реальности наш заказчик  может работать с довольно широкими картами. [/QUOTE]
Предлагаем рассмотреть такой вариант для ОС Windows: 1) построение линии ортодромии (с сохранением этой линии в виде объекта).  2) построение вдоль линии ортодромии зоны с заданной шириной  3) выбор высот из матрицы в пределах построенной зоны.  На этой картинке линия (и соответствующая зона) - немного изогнутые.  
    [/QUOTE]

В Гис Операторе нет опции создания прямоугольной зоны, только по радиусу. И линия получается не изогнутой (Проверяли на глобусе в проекции Меркатора).
Отклонения в плане и точность матрицы высот
 
Набросал пример:
Орртодромия проходит по небольшой карте в районе Пакистана по диагонале и пересекает границу зон 41 и 42.
Сама карта собрана в зоне 41. Проекция Гаусса-Крюггера. Система координат СК42.
По карте рассчитана матрица высот с дискретом 50 м.

Координаты ортодромии:
Начало p1 = 25°00'00,00" СШ    63°55'00,00" ВД
Конец  p2 = 26°50'00,00" СШ    66°45'00,00" ВД

Длина ортодромии L = 349 054 м (Функция mapRealDistance)
Ширина вырезки W = 50 000 м (+- 25 км)
Дискрет (шаг) dx = 100 м
Начало вырезки за dStart (25 000 м) до начала ортодромии
Конец вырезки через dStop (5 000 м) после окончания ортодромии
Длина вырезки в дискретах  col = 3792 ((L + dStart + dStop)/dx + 1)
Ширина вырезки в дискретах row = 501 (W/dx + 1)

Расчет угла вырезки от которого идет отсчет в плане по dx:
cosa = (p2.x - p1.x)/L;
sina = (p2.y - p1.y)/L;

BL.x = p1.x + dStart*(sina - cosa);
BL.y = p1.y - dStart*(cosa + sina);


// Расчет текущей точке в плане, по которой береться высота:
for (int ri = 0; ri < row; ri++) {
   ...
   for (int ci=0; ci<col; ci++) {
       ...
       P.x = BL.x - ri*dx*sina + ci*dx*cosa;
       P.y = BL.y + ri*dx*cosa + ci*dx*sina;
       double curr_h = mapGetHeightValue(hmap, P.x, P.y);
       ...
   }
}


Если брать координаты текущей точки P в центре вырезки при ri = 250(Линия ортодромии) и координаты ортодромии в данной точке
по функциям mapInversePositionComputation (Получаем азимут ортодромии) и mapDirectPositionComputation (Получаем текущую точку с шагом dx),
а затем вычислять расстояние между ними (mapRealDistance), то получим заметные отклонения.

В начале и конце ортодромии отклонение составило порядка 29 м. Максимальное отклонение было в середине и составило 117 м.

Соответственно, такие же отклонения можно наблюдать по всей вырезке.
Если карта будет состоять из 3 зон, и ортодромия находится на краю, то отклонения серьезно возрастают.

Понятное дело, что можно отказаться от работы в плане и высчитывать каждую точку вырезки функциями по азимутам, но хотелось бы иметь пригодный для работы план.
Страницы: 1 2 След.



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

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