Russian Qt Forum

Qt => Вопросы новичков => Тема начата: John.Fefs от Март 07, 2015, 16:02



Название: Помощ в создание оффлайн интерактивной карты
Отправлено: John.Fefs от Март 07, 2015, 16:02
Дорогие форумчане помогите кто сможет :) Я занялся Qt меньше  месяца назад. Многому научился из примеров и литературы в сети, но вот решения этой проблемы так и не нашел.

Мне нужно написать оффлайн интерактивную карту, которая не подгружалась бы с интернета. За основу я взял карту OpenStreetMaps и нарезал ее на отдельные изображения в формате png.
Получилась одно основное изображение в моем случае города Санкт-Петербург, его я мысленно поделил сеткой, и дальше по прогрессии сделал отдельные увеличенные изображения города.
Проблема заключается в том, что ни как не могу придумать как реализовать увеличение карты, прокруткой колесика мыши.

Как я себе представляю это:
1) Нужно вывести на форму изображение
2) Поделить его сеткой
3) В случае если указатель находится на определенном квадрате сетки, при прокрутке мыши увеличиваем основное изображение, и поверх него накладываем уже более четкие и детальные изображения карты. И при перемещение по карте также должны подгружаться крайние элементы карты от этого.
Я так понимаю онлайн карты реализованы так же.

Подскажите какие функции и методы нужно использовать, и если есть примеры реализации (если они все таки существуют)?  Я думаю это будет полезно не только мне.
Прошу помогите, заранее спасибо!


Название: Re: Помощ в создание оффлайн интерактивной карты
Отправлено: Igors от Март 07, 2015, 16:20
Так а в чем проблема? Как подгружать - есть удобный класс QPixmapCache. В любой момент времени у Вас есть текущий масштаб и размер видимой области. Ну и грузите все что покрывает эту область.


Название: Re: Помощ в создание оффлайн интерактивной карты
Отправлено: John.Fefs от Март 08, 2015, 21:20
Так а в чем проблема? Как подгружать - есть удобный класс QPixmapCache. В любой момент времени у Вас есть текущий масштаб и размер видимой области. Ну и грузите все что покрывает эту область.


Проблема в том с чего начать)
Я создаю QLabel вывожу на него основное изображение, при этом zoom=1, а вот как быть дальше ступор и куча вопросов. Например как дальше быть для zoom=2,3,4... То есть как именно на видимую область наложить определенную картинку.

По QPixmapCache я прочел в документации, но примеров использования для моего случая так и не нашел. Если можно пример использования именно для моего случая?
Или где можно прочесть как это делается?
Результат должен напоминать http://www.kartaspb.ru.


Название: Re: Помощ в создание оффлайн интерактивной карты
Отправлено: Old от Март 08, 2015, 21:30
Есть такой проект marble, он написан с использованием Qt, там один из бекендов умеет рендерить openstreetmap карты. Посмотрите на него, возможно, проще будет написать свой источник данных (берущий локальные данные) и использовать готовый движок для рендеринга карт со всеми кайфами.


Название: Re: Помощ в создание оффлайн интерактивной карты
Отправлено: popper от Март 08, 2015, 22:28
Marble работает и с локально хранящимися нарезками карт (тэйлами)


Название: Re: Помощ в создание оффлайн интерактивной карты
Отправлено: Igors от Март 09, 2015, 10:53
Проблема в том с чего начать)
Я создаю QLabel вывожу на него основное изображение, при этом zoom=1, а вот как быть дальше ступор и куча вопросов. Например как дальше быть для zoom=2,3,4... То есть как именно на видимую область наложить определенную картинку.
Есть максимальный реальный, "географический" размер, напр 100х100 километров. Каждый кусок нарезанной карты должен знать (в тех же километрах) свою позицию левого верхнего угла и свою ширину/высоту. Это примерно такая структура
Код
C++ (Qt)
typedef QPair <QRectF, QPixmap> TImage;
. Откуда возьмется QRectF - Ваши проблемы, напр из имени файла, но иметь это необходимо, иначе неизвестно какую картинку где выводить.

Также у Вас есть скроллируемый виджет (см QScrollArea), известен его "полный" размер (QRect), видимая часть (QRect) и позиции скроллеров scrollX и scrollY. Это все в пыкселях.

Масштаб scale определяете как
Цитировать
real_size * scale = pixel_size
Это "начальный" масштаб который предъявляется юзеру как (якобы) 1:1. Изначально задаете макс начальный размер картинки напр 800x800. Тогда
Цитировать
scale = 800 / 100 = 8. (где 100 - те самые 100 км)
При рисовании вычисляете видимую часть
Код
C++ (Qt)
QRectF realR(scrollX / scale, scrollY / scale, width() / scale, height() / scale);
и находите все нужные "куски". Ну дальше уже устал писать - по-моему все очевидно :) Постарайтесь переварить это, потом (если надо) поговорим дальше


Название: Re: Помощ в создание оффлайн интерактивной карты
Отправлено: John.Fefs от Март 18, 2015, 13:58
Есть такой проект marble, он написан с использованием Qt, там один из бекендов умеет рендерить openstreetmap карты. Посмотрите на него, возможно, проще будет написать свой источник данных (берущий локальные данные) и использовать готовый движок для рендеринга карт со всеми кайфами.
Всем спасибо, я воспользовался их виджетом,подключил все библиотеки и тд., долго разбирался конечно, marble отлично сохраняет карты в кэш ;D

Есть еще вопросы:
1) Мне нужно установить начало координат (0,0) в определенной точке карты, так как данные на приемник будут поступать в декартовых координатах относительно этой точки(передатчика), при определенном масштабе. Как это лучше реализовать?
2) Как потом эти координаты перевести в географические?


Название: Re: Помощ в создание оффлайн интерактивной карты
Отправлено: Kurles от Март 18, 2015, 14:57
2) Как потом эти координаты перевести в географические?
Если за основу взят рендер OpenStreetMaps и его формат slippy map (http://wiki.openstreetmap.org/wiki/RU:Slippy_Map), то вот код:
Код
C++ (Qt)
QPointF tileForCoordinate(qreal lat, qreal lng, int zoom)
{
   qreal zn = static_cast<qreal>(1 << zoom);
   qreal tx = (lng + 180.0) / 360.0;
   qreal ty = (1.0 - log(tan(lat * pi / 180.0) +
                         1.0 / cos(lat * pi / 180.0)) / pi) / 2.0;
   return QPointF(tx * zn, ty * zn);
}
 
qreal longitudeFromTile(qreal tx, int zoom)
{
   qreal zn = static_cast<qreal>(1 << zoom);
   qreal lat = tx / zn * 360.0 - 180.0;
   return lat;
}
 
qreal latitudeFromTile(qreal ty, int zoom)
{
   qreal zn = static_cast<qreal>(1 << zoom);
   qreal n = pi - 2 * pi * ty / zn;
   qreal lng = 180.0 / pi * atan(0.5 * (exp(n) - exp(-n)));
   return lng;
}
 


Название: Re: Помощ в создание оффлайн интерактивной карты
Отправлено: deMax от Март 19, 2015, 12:39
Многому научился из примеров и литературы в сети, но вот решения этой проблемы так и не нашел.
http://sourceforge.net/projects/qmapcontrol/
Она на Qt и она работает.

А теперь как сделать:
берете виджет(обычный или QGlWidget), переопределяете paintevent и рисуете.
У вас 3 параметра zoom, centerX, centerY. (долгота и широта вам нужна будет для отображения объектов на карте, для рисования карты она не нужна вообще).
0<=zoom<18(или 20 или 24 для разных карт по разному )
0<=centerX<mapWidth, где mapWidth = 256* (1<<zoom)

колесо мыши меняет zoom на dZoom, соответственно "centerX=centerX<<dZoom" это приближение по центру экрана, приближение относительно мыши как то так "centerX= ((centerX+mouseX)<< dZoom)-mouseX;"

тайлы тут: "tile.openstreetmap.org/%1/%2/%3.png" где 1-zoom 2-x 3-y

рисование по сути простое (только отсечку по краям экрана добавьте)
for(int numX=0; numX<(1<<zoom); ++numX)
  for(int numY=0; numY<(1<<zoom); ++numY)
    painter->drawRect(numY*256-centerX, numY*256-centerY, image(zoom,numX,numY));


Название: Re: Помощ в создание оффлайн интерактивной карты
Отправлено: deMax от Март 23, 2015, 08:42
Забыл про размер добавить, если вся OSM весит 500Gb в векторном формате. То ее растровый формат (всей карты) для zoom=7 - 50Mb, zoom=10 - 1.59Gb (а дома только на 12-13 масштабе появляются).