Russian Qt Forum
Ноябрь 05, 2024, 22:15 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Помощ в создание оффлайн интерактивной карты  (Прочитано 10364 раз)
John.Fefs
Гость
« : Март 07, 2015, 16:02 »

Дорогие форумчане помогите кто сможет Улыбающийся Я занялся Qt меньше  месяца назад. Многому научился из примеров и литературы в сети, но вот решения этой проблемы так и не нашел.

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

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

Подскажите какие функции и методы нужно использовать, и если есть примеры реализации (если они все таки существуют)?  Я думаю это будет полезно не только мне.
Прошу помогите, заранее спасибо!
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Март 07, 2015, 16:20 »

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

Так а в чем проблема? Как подгружать - есть удобный класс QPixmapCache. В любой момент времени у Вас есть текущий масштаб и размер видимой области. Ну и грузите все что покрывает эту область.


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

По QPixmapCache я прочел в документации, но примеров использования для моего случая так и не нашел. Если можно пример использования именно для моего случая?
Или где можно прочесть как это делается?
Результат должен напоминать http://www.kartaspb.ru.
« Последнее редактирование: Март 08, 2015, 21:23 от John.Fefs » Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #3 : Март 08, 2015, 21:30 »

Есть такой проект marble, он написан с использованием Qt, там один из бекендов умеет рендерить openstreetmap карты. Посмотрите на него, возможно, проще будет написать свой источник данных (берущий локальные данные) и использовать готовый движок для рендеринга карт со всеми кайфами.
Записан
popper
Гость
« Ответ #4 : Март 08, 2015, 22:28 »

Marble работает и с локально хранящимися нарезками карт (тэйлами)
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Март 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);
и находите все нужные "куски". Ну дальше уже устал писать - по-моему все очевидно Улыбающийся Постарайтесь переварить это, потом (если надо) поговорим дальше
Записан
John.Fefs
Гость
« Ответ #6 : Март 18, 2015, 13:58 »

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

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

Сообщений: 480



Просмотр профиля
« Ответ #7 : Март 18, 2015, 14:57 »

2) Как потом эти координаты перевести в географические?
Если за основу взят рендер OpenStreetMaps и его формат 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;
}
 
Записан

Код
C++ (Qt)
while(!asleep()) sheep++;
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #8 : Март 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));
« Последнее редактирование: Март 19, 2015, 14:16 от deMax » Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #9 : Март 23, 2015, 08:42 »

Забыл про размер добавить, если вся OSM весит 500Gb в векторном формате. То ее растровый формат (всей карты) для zoom=7 - 50Mb, zoom=10 - 1.59Gb (а дома только на 12-13 масштабе появляются).
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.282 секунд. Запросов: 23.