Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
305 KeyOz 1
/*
2
*
3
* This file is part of QMapControl,
4
* an open-source cross-platform map widget
5
*
6
* Copyright (C) 2007 - 2008 Kai Winter
7
*
8
* This program is free software: you can redistribute it and/or modify
9
* it under the terms of the GNU Lesser General Public License as published by
10
* the Free Software Foundation, either version 3 of the License, or
11
* (at your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
* GNU Lesser General Public License for more details.
17
*
18
* You should have received a copy of the GNU Lesser General Public License
19
* along with QMapControl. If not, see <http://www.gnu.org/licenses/>.
20
*
21
* Contact e-mail: kaiwinter@gmx.de
22
* Program URL   : http://qmapcontrol.sourceforge.net/
23
*
24
*/
25
 
26
#include "layermanager.h"
27
namespace qmapcontrol
28
{
29
    LayerManager::LayerManager(MapControl* mapcontrol, QSize size)
30
        :mapcontrol(mapcontrol), scroll(QPoint(0,0)), size(size), whilenewscroll(QPoint(0,0))
31
    {
32
        // genauer berechnen?
33
        offSize = size *2;
34
        composedOffscreenImage = QPixmap(offSize);
35
        composedOffscreenImage2 = QPixmap(offSize);
36
        zoomImage = QPixmap(size);
37
        zoomImage.fill(Qt::white);
38
        screenmiddle = QPoint(size.width()/2, size.height()/2);
39
    }
40
 
41
 
42
    LayerManager::~LayerManager()
43
    {
44
        mylayers.clear();
45
    }
46
 
47
    QPointF LayerManager::currentCoordinate() const
48
    {
49
        return mapmiddle;
50
    }
51
 
52
    QPixmap LayerManager::getImage() const
53
    {
54
        return composedOffscreenImage;
55
    }
56
 
57
    Layer* LayerManager::layer() const
58
    {
59
        Q_ASSERT_X(mylayers.size()>0, "LayerManager::getLayer()", "No layers were added!");
60
        return mylayers.first();
61
    }
62
 
63
    Layer* LayerManager::layer(const QString& layername) const
64
    {
65
        QListIterator<Layer*> layerit(mylayers);
66
        while (layerit.hasNext())
67
        {
68
            Layer* l = layerit.next();
69
            if (l->layername() == layername)
70
                return l;
71
        }
72
        return 0;
73
    }
74
 
75
    QList<QString> LayerManager::layers() const
76
    {
77
        QList<QString> keys;
78
        QListIterator<Layer*> layerit(mylayers);
79
        while (layerit.hasNext())
80
        {
81
            keys.append(layerit.next()->layername());
82
        }
83
        return keys;
84
    }
85
 
86
 
87
    void LayerManager::scrollView(const QPoint& point)
88
    {
89
        scroll += point;
90
        zoomImageScroll+=point;
91
        mapmiddle_px += point;
92
 
93
        mapmiddle = layer()->mapadapter()->displayToCoordinate(mapmiddle_px);
94
        if (!checkOffscreen())
95
        {
96
            newOffscreenImage();
97
        }
98
        else
99
        {
100
            moveWidgets();
101
        }
102
    }
103
 
104
    void LayerManager::moveWidgets()
105
    {
106
        QListIterator<Layer*> it(mylayers);
107
        while (it.hasNext())
108
        {
109
            it.next()->moveWidgets(mapmiddle_px);
110
        }
111
    }
112
 
113
    void LayerManager::setView(const QPointF& coordinate)
114
    {
115
        mapmiddle_px = layer()->mapadapter()->coordinateToDisplay(coordinate);
116
        mapmiddle = coordinate;
117
 
118
        //TODO: muss wegen moveTo() raus
119
        if (!checkOffscreen())
120
        {
121
            newOffscreenImage();
122
        }
123
        else
124
        {
125
            //TODO:
126
            // verschiebung ausrechnen
127
            // oder immer neues offscreenimage
128
            newOffscreenImage();
129
        }
130
    }
131
 
132
    void LayerManager::setView(QList<QPointF> coordinates)
133
    {
134
        setMiddle(coordinates);
135
        // mapcontrol->update();
136
    }
137
 
138
    void LayerManager::setViewAndZoomIn(const QList<QPointF> coordinates)
139
    {
140
        while (containsAll(coordinates))
141
        {
142
            setMiddle(coordinates);
143
            zoomIn();
144
        }
145
 
146
 
147
        if (!containsAll(coordinates))
148
        {
149
            zoomOut();
150
        }
151
 
152
        mapcontrol->update();
153
    }
154
 
155
    void LayerManager::setMiddle(QList<QPointF> coordinates)
156
    {
157
        int sum_x = 0;
158
        int sum_y = 0;
159
        for (int i=0; i<coordinates.size(); i++)
160
        {
161
            // mitte muss in px umgerechnet werden, da aufgrund der projektion die mittebestimmung aus koordinaten ungenau ist
162
            QPoint p = layer()->mapadapter()->coordinateToDisplay(coordinates.at(i));
163
            sum_x += p.x();
164
            sum_y += p.y();
165
        }
166
        QPointF middle = layer()->mapadapter()->displayToCoordinate(QPoint(sum_x/coordinates.size(), sum_y/coordinates.size()));
167
        // middle in px rechnen!
168
 
169
        setView(middle);
170
    }
171
 
172
    bool LayerManager::containsAll(QList<QPointF> coordinates) const
173
    {
174
        QRectF bb = getViewport();
175
        bool containsall = true;
176
        for (int i=0; i<coordinates.size(); i++)
177
        {
178
            if (!bb.contains(coordinates.at(i)))
179
                return false;
180
        }
181
        return containsall;
182
    }
183
    QPoint LayerManager::getMapmiddle_px() const
184
    {
185
        return mapmiddle_px;
186
    }
187
 
188
    QRectF LayerManager::getViewport() const
189
    {
190
        QPoint upperLeft = QPoint(mapmiddle_px.x()-screenmiddle.x(), mapmiddle_px.y()+screenmiddle.y());
191
        QPoint lowerRight = QPoint(mapmiddle_px.x()+screenmiddle.x(), mapmiddle_px.y()-screenmiddle.y());
192
 
193
        QPointF ulCoord = layer()->mapadapter()->displayToCoordinate(upperLeft);
194
        QPointF lrCoord = layer()->mapadapter()->displayToCoordinate(lowerRight);
195
 
196
        QRectF coordinateBB = QRectF(ulCoord, QSizeF( (lrCoord-ulCoord).x(), (lrCoord-ulCoord).y()));
197
        return coordinateBB;
198
    }
199
 
200
    void LayerManager::addLayer(Layer* layer)
201
    {
202
        mylayers.append(layer);
203
 
204
        layer->setSize(size);
205
 
206
        connect(layer, SIGNAL(updateRequest(QRectF)),
207
                this, SLOT(updateRequest(QRectF)));
208
        connect(layer, SIGNAL(updateRequest()),
209
                this, SLOT(updateRequest()));
210
 
211
        if (mylayers.size()==1)
212
        {
213
            setView(QPointF(0,0));
214
        }
215
    }
216
 
217
    void LayerManager::newOffscreenImage(bool clearImage, bool showZoomImage)
218
    {
219
        //      qDebug() << "LayerManager::newOffscreenImage()";
220
        whilenewscroll = mapmiddle_px;
221
 
222
        if (clearImage)
223
        {
224
            composedOffscreenImage2.fill(Qt::white);
225
        }
226
 
227
        QPainter painter(&composedOffscreenImage2);
228
        if (showZoomImage)
229
        {
230
            painter.drawPixmap(screenmiddle.x()-zoomImageScroll.x(), screenmiddle.y()-zoomImageScroll.y(),zoomImage);
231
        }
232
        //only draw basemaps
233
        for (int i=0; i<mylayers.count(); i++)
234
        {
235
            Layer* l = mylayers.at(i);
236
            if (l->isVisible())
237
            {
238
                if (l->layertype() == Layer::MapLayer)
239
                {
240
                    l->drawYourImage(&painter, whilenewscroll);
241
                }
242
            }
243
        }
244
 
245
        composedOffscreenImage = composedOffscreenImage2;
246
        scroll = mapmiddle_px-whilenewscroll;
247
 
248
        mapcontrol->update();
249
    }
250
 
251
    void LayerManager::zoomIn()
252
    {
253
        QCoreApplication::processEvents();
254
 
255
        ImageManager::instance()->abortLoading();
256
        // layer rendern abbrechen?
257
        zoomImageScroll = QPoint(0,0);
258
 
259
        zoomImage.fill(Qt::white);
260
        QPixmap tmpImg = composedOffscreenImage.copy(screenmiddle.x()+scroll.x(),screenmiddle.y()+scroll.y(), size.width(), size.height());
261
 
262
        QPainter painter(&zoomImage);
263
        painter.save();
264
        painter.translate(screenmiddle);
265
        painter.scale(2, 2);
266
        painter.translate(-screenmiddle);
267
 
268
        painter.drawPixmap(0,0,tmpImg);
269
        painter.restore();
270
 
271
        QListIterator<Layer*> it(mylayers);
272
        //TODO: remove hack, that mapadapters wont get set zoom multiple times
273
        QList<const MapAdapter*> doneadapters;
274
        while (it.hasNext())
275
        {
276
            Layer* l = it.next();
277
            if (!doneadapters.contains(l->mapadapter()))
278
            {
279
                l->zoomIn();
280
                doneadapters.append(l->mapadapter());
281
            }
282
        }
283
        mapmiddle_px = layer()->mapadapter()->coordinateToDisplay(mapmiddle);
284
        whilenewscroll = mapmiddle_px;
285
 
286
        newOffscreenImage();
287
 
288
    }
289
 
290
    bool LayerManager::checkOffscreen() const
291
    {
292
        // calculate offscreenImage dimension (px)
293
        QPoint upperLeft = mapmiddle_px - screenmiddle;
294
        QPoint lowerRight = mapmiddle_px + screenmiddle;
295
        QRect viewport = QRect(upperLeft, lowerRight);
296
 
297
        QRect testRect = layer()->offscreenViewport();
298
 
299
        if (!testRect.contains(viewport))
300
        {
301
            return false;
302
        }
303
 
304
        return true;
305
    }
306
    void LayerManager::zoomOut()
307
    {
308
        QCoreApplication::processEvents();
309
        ImageManager::instance()->abortLoading();
310
        zoomImageScroll = QPoint(0,0);
311
        zoomImage.fill(Qt::white);
312
        QPixmap tmpImg = composedOffscreenImage.copy(screenmiddle.x()+scroll.x(),screenmiddle.y()+scroll.y(), size.width(), size.height());
313
        QPainter painter(&zoomImage);
314
        painter.translate(screenmiddle);
315
        painter.scale(0.5,0.5);
316
        painter.translate(-screenmiddle);
317
        painter.drawPixmap(0,0,tmpImg);
318
 
319
        painter.translate(screenmiddle);
320
        painter.scale(2,2);
321
        painter.translate(-screenmiddle);
322
 
323
        QListIterator<Layer*> it(mylayers);
324
        //TODO: remove hack, that mapadapters wont get set zoom multiple times
325
        QList<const MapAdapter*> doneadapters;
326
        while (it.hasNext())
327
        {
328
            Layer* l = it.next();
329
            if (!doneadapters.contains(l->mapadapter()))
330
            {
331
                l->zoomOut();
332
                doneadapters.append(l->mapadapter());
333
            }
334
        }
335
        mapmiddle_px = layer()->mapadapter()->coordinateToDisplay(mapmiddle);
336
        whilenewscroll = mapmiddle_px;
337
        newOffscreenImage();
338
    }
339
 
340
    void LayerManager::setZoom(int zoomlevel)
341
    {
342
        int current_zoom;
343
        if (layer()->mapadapter()->minZoom() < layer()->mapadapter()->maxZoom())
344
        {
345
            current_zoom = layer()->mapadapter()->currentZoom();
346
        }
347
        else
348
        {
349
            current_zoom = layer()->mapadapter()->minZoom() - layer()->mapadapter()->currentZoom();
350
        }
351
 
352
 
353
        if (zoomlevel < current_zoom)
354
        {
355
            for (int i=current_zoom; i>zoomlevel; i--)
356
            {
357
                zoomOut();
358
            }
359
        }
360
        else
361
        {
362
            for (int i=current_zoom; i<zoomlevel; i++)
363
            {
364
                zoomIn();
365
            }
366
        }
367
    }
368
 
369
    void LayerManager::mouseEvent(const QMouseEvent* evnt)
370
    {
371
        QListIterator<Layer*> it(mylayers);
372
        while (it.hasNext())
373
        {
374
            Layer* l = it.next();
375
            if (l->isVisible())
376
            {
377
                l->mouseEvent(evnt, mapmiddle_px);
378
            }
379
        }
380
    }
381
 
382
    void LayerManager::updateRequest(QRectF rect)
383
    {
384
        const QPoint topleft = mapmiddle_px - screenmiddle;
385
 
386
        QPointF c = rect.topLeft();
387
 
388
        if (getViewport().contains(c) || getViewport().contains(rect.bottomRight()))
389
        {
390
            // QPoint point = getLayer()->getMapAdapter()->coordinateToDisplay(c);
391
            // QPoint finalpoint = point-topleft;
392
            // QRect rect_px = QRect(int(finalpoint.x()-(rect.width()-1)/2), int(finalpoint.y()-(rect.height()-1)/2),
393
            //  int(rect.width()+1), int(rect.height()+1));
394
            //
395
            // mapcontrol->updateRequest(rect_px);
396
            mapcontrol->update();
397
            // newOffscreenImage();
398
        }
399
    }
400
    void LayerManager::updateRequest()
401
    {
402
        newOffscreenImage();
403
    }
404
    void LayerManager::forceRedraw()
405
    {
406
        newOffscreenImage();
407
    }
408
    void LayerManager::removeZoomImage()
409
    {
410
        zoomImage.fill(Qt::white);
411
        forceRedraw();
412
    }
413
 
414
    void LayerManager::drawGeoms(QPainter* painter)
415
    {
416
        QListIterator<Layer*> it(mylayers);
417
        while (it.hasNext())
418
        {
419
            Layer* l = it.next();
420
            if (l->layertype() == Layer::GeometryLayer && l->isVisible())
421
            {
422
                l->drawYourGeometries(painter, mapmiddle_px, layer()->offscreenViewport());
423
            }
424
        }
425
    }
426
    void LayerManager::drawImage(QPainter* painter)
427
    {
428
        painter->drawPixmap(-scroll.x()-screenmiddle.x(),
429
                            -scroll.y()-screenmiddle.y(),
430
                            composedOffscreenImage);
431
    }
432
 
433
    int LayerManager::currentZoom() const
434
    {
435
        return layer()->mapadapter()->currentZoom();
436
    }
437
 
438
    void LayerManager::resize(QSize newSize)
439
    {
440
        size = newSize;
441
        offSize = newSize *2;
442
        composedOffscreenImage = QPixmap(offSize);
443
        composedOffscreenImage2 = QPixmap(offSize);
444
        zoomImage = QPixmap(newSize);
445
        zoomImage.fill(Qt::white);
446
 
447
        screenmiddle = QPoint(newSize.width()/2, newSize.height()/2);
448
 
449
        QListIterator<Layer*> it(mylayers);
450
        while (it.hasNext())
451
        {
452
            Layer* l = it.next();
453
            l->setSize(newSize);
454
        }
455
 
456
        newOffscreenImage();
457
    }
458
}