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

[BUG_REPORT] Ошибка хранения пиксельных координат

Поиск  Пользователи  Правила  Войти
Форум » Linux » Средства разработки ГИС-приложений для Linux
Страницы: 1
RSS
[BUG_REPORT] Ошибка хранения пиксельных координат
 
Данное поведение точно есть на 11 версии, с которой мы работаем сейчас.
Воспроизведение:
0. создаём пользовательский слой следующим образом:
Код
HMAP PanoramaUtility::createMap(const QString &path, const LayerInfo &info)
{
    QTextCodec* codec = QTextCodec::codecForName( "KOI8-R");
    CREATESITE crs;
    memset( &crs, 0, sizeof( crs));
    crs.Length = sizeof( crs);
    double lat = 384, lon = 512;
    screen2geo( lat, lon);
    lat *= M_PI / 180.;
    lon *= M_PI / 180.;
    crs.AxisMeridian = info.m_axisMeridian == 0 ? lat : info.m_axisMeridian;
    crs.MainPointParallel = info.m_mainParallel == 0 ? lon : info.m_mainParallel;
    crs.Scale = info.m_scale;
    crs.MapType = BLANK;//CK_42;
    crs.MaterialProjection = MERCATORMAP;//GAUSSCONFORMAL;
    int maxLen = info.m_name.length() > 31 ? 31 : info.m_name.length();
    memcpy( crs.MapName, codec->fromUnicode( info.m_name).data(), maxLen);

    QDir dr( path);
    if( dr.exists())
    {
        removeDir( path);
    }
    dr.mkpath( path);

    QString layerName = path + "/" + info.m_name + ".sit";
    QFileInfo fli( DEFAULT_OBJECTS_CLASSIFIER);
    QString rscName = path + "/" + fli.fileName();
    QFile fl( DEFAULT_OBJECTS_CLASSIFIER);
    fl.copy( rscName);

   HMAP hMap = mapCreateSite( codec->fromUnicode( layerName).data(),
                              codec->fromUnicode( rscName).data(),
                              &crs);
   mapSetSiteRangeScaleVisible( hMap, 0, 1, 40000000);
   system("sync");
   return hMap;
}
При создании карты задаём масштаб 10000000.
1. На нормальную (официальную) карту масштабом 25к добавляем данную карту:
Код
void PanoramaUtility::openWorkingLayerPath(const QString &workingLayer)
{
    if( m_descriptor == 0) return;
    if( workingLayer.isEmpty()) return;
    QTextCodec* codec = QTextCodec::codecForName( "KOI8-R");
    QByteArray tmpMapData = codec->fromUnicode( workingLayer);
    qDebug() << "PanoramaUtility::openWorkingLayerPath" << workingLayer;
    m_workingLayer = mapGetSiteIdentByName( m_descriptor, tmpMapData.data());
    if( m_workingLayer == 0)
    {
        if( mapOpenSiteForMapEx( m_descriptor, tmpMapData.data(), GENERIC_READ | GENERIC_WRITE, 0) == 0)
        {
            qDebug() << "PanoramaUtility::openDataToMapPrivate ERROR mapOpenSiteForMapEx";
        }
        m_workingLayer = mapGetSiteIdentByName( m_descriptor, tmpMapData.data());
        if( m_workingLayer == 0)
        {
            qDebug() << "PanoramaUtility::openWorkingLayerPath ERROR mapGetSiteIdentByName = 0";
            return;
        }
    }
    else
    {
        mapSetSiteViewOrder( m_descriptor, mapGetSiteNumber( m_descriptor, m_workingLayer), 1);
    }
    m_workingLayerPath = workingLayer;
}
2. Отображаем карту
3. Выгружаем карту
Код
void PanoramaUtility::closeWorkingLayer()
{
    if( m_descriptor == 0)
    {
        m_workingLayerPath.clear();
        m_workingLayer = 0;
        return;
    }
    QTextCodec* codec = QTextCodec::codecForName( "KOI8-R");
    if( m_workingLayer != 0)
    {
        QByteArray tmpOpenedData = codec->fromUnicode( m_workingLayerPath);
        HSITE hsit = mapGetSiteIdentByName( m_descriptor, tmpOpenedData.data());
        qDebug() << "PanoramaUtility::openWorkingLayerPath()" << hsit << m_workingLayerPath;
        if( hsit != 0)
        {
            if( mapCloseSiteForMap( m_descriptor, hsit) == 0)
            {
                qDebug() << "PanoramaUtility::openWorkingLayerPath() error" << m_workingLayerPath;
            }
        }
        else
        {
            qDebug() << "PanoramaUtility::openWorkingLayerPath() error identifying " << m_workingLayerPath;
        }
        m_workingLayer = 0;
    }
    if( !m_workingLayerPath.isEmpty())
    {
        if( m_openedData.contains( m_workingLayerPath))
        {
            m_openedData.removeOne( m_workingLayerPath);
            m_workingLayer = 0;
            m_workingLayerPath.clear();
            return;
        }
    }
    m_workingLayerPath.clear();
}
4. Отображаем карту.
5. Перемещаем...
6. Масштабируем:
Ожидаемая реакция: масштабирование приводит к изменению только масштаба
Фактическая реакция: масштабирование приводит к переносу отображения в другую позицию и изменение масштаба
Наблюдения: Выгрузка слоя не изменяет внутренних пиксельных размеров карты и, соответственно, хранимых координат центра экрана относительно фактических в библиотеках, до момента изменения масштаба.
После изменения масштаба происходит некий внутренний процесс, который пересчитывает размеры карты и приводит к несоответствию хранимых пиксельных координат относительно фактических в библиотеке, что приводит к последующему некорректному отображению
карты в точке, соответствующей другим географическим координатам.

Если этот баг в новой версии решён, то прошу "понять и простить". :)
ЗЫ: В рабочем проекте я обошёл эту проблему костылём.
Изменено: Александр Лазарев - 07.11.2018 11:53:41
 
Приветствую!

Не совсем понятно что именно Вы считаете ошибкой, но суть понятна. Да, при изменении масштаба меняются габариты карты, в случае если необходимо (добавились объекты, которые выходят за пределы текущей области карты). Поэтому не стоит привязываться к координатам в пикселях.
Если очень хочется привязаться к пикселям, то можно считать не от левого верхнего угла, а, например, от центра карты.

С уважением,
Матвеев П.В.
 
Я когда решил поставить последний пакет вообще получил пользовательские карты с рамкой на всю планету, два дня искал проблему (проявлялась после первого масштабирования), потом просто откатил пакет gisdesigner на предыдущую версию и всё снова заработало как часы.
 
Цитата
Павел Матвеев написал:
Приветствую!

Не совсем понятно что именно Вы считаете ошибкой, но суть понятна. Да, при изменении масштаба меняются габариты карты, в случае если необходимо (добавились объекты, которые выходят за пределы текущей области карты). Поэтому не стоит привязываться к координатам в пикселях.
Если очень хочется привязаться к пикселям, то можно считать не от левого верхнего угла, а, например, от центра карты.

С уважением,
Матвеев П.В.
Пиксели у нас используются для внутреннего хранения и для перемещения карты (мышка к сожалению даёт не градусы, а пиксели), для перерисовки карты в определённых координатах мы каждый раз пересчитываем географические координаты в пиксельные для отображения в нужном месте. Поэтому если дополнительная карта выгружена, то размеры нужно сразу пересчитывать, а не ждать изменения масштаба, потому что потом пользователь начинает масштабировать и у него слетает отображение. ИМХО.
 
Приветствую!

Я понимаю почему Вы используете пиксели) я тоже использовал их для хранения верхнего левого угла карты внутри элемента управления. Потом перешел на plane.
Мышка дает вам пиксели, конечно, но пиксели относительно элемента управления или дисплея, а не карты.

Повторюсь, не стоит привязываться к пикселям. Координаты в них меняются. Они могут меняться при добавлении пользовательских карт к основной, при создании объектов на карте, и в ряде других случаев. Пересчитывать размеры каждый раз при добавлении нового объекта на карту - это трата времени. Проще не хранить пиксели и не привязываться к ним. В момент когда нужны координаты в пикселях их всегда можно получить, использовать и забыть снова. ИМХО.


С уважением,
Матвеев П.В.
 
Цитата
Павел Матвеев написал:
Приветствую!

Я понимаю почему Вы используете пиксели) я тоже использовал их для хранения верхнего левого угла карты внутри элемента управления. Потом перешел на plane.
Мышка дает вам пиксели, конечно, но пиксели относительно элемента управления или дисплея, а не карты.

Повторюсь, не стоит привязываться к пикселям. Координаты в них меняются. Они могут меняться при добавлении пользовательских карт к основной, при создании объектов на карте, и в ряде других случаев. Пересчитывать размеры каждый раз при добавлении нового объекта на карту - это трата времени. Проще не хранить пиксели и не привязываться к ним. В момент когда нужны координаты в пикселях их всегда можно получить, использовать и забыть снова. ИМХО.


С уважением,
Матвеев П.В.
В общем подытожим:
1. Я считаю это багом, что при вызове mapOpenSiteForMapEx/mapCloseSiteForMap не происходит перерасчёта границ в пикселях.
2. Если это не баг, тогда тему можно закрыть, удалить и забыть.
 
Здравствуйте!

Вам нужно вручную сохранять координаты в метрах перед любыми изменениями  состава карт и восстанавливать их после. Реализацию можно посмотреть в исходных текстах графических компонентов ГИС Конструктор последней версии (qdmwina.cpp, /usr/share/gisdesigner/examples/sources), на примере функций SetMapLeftTopPlane и GetMapLeftTopPlane.

Спасибо за ожидание.
Страницы: 1
Читают тему (гостей: 1)



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

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