Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
674 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.translate(screenmiddle);
264
        painter.scale(2, 2);
265
        painter.translate(-screenmiddle);
266
 
267
        painter.drawPixmap(0,0,tmpImg);
268
 
269
        QListIterator<Layer*> it(mylayers);
270
        //TODO: remove hack, that mapadapters wont get set zoom multiple times
271
        QList<const MapAdapter*> doneadapters;
272
        while (it.hasNext())
273
        {
274
            Layer* l = it.next();
275
            if (!doneadapters.contains(l->mapadapter()))
276
            {
277
                l->zoomIn();
278
                doneadapters.append(l->mapadapter());
279
            }
280
        }
281
        mapmiddle_px = layer()->mapadapter()->coordinateToDisplay(mapmiddle);
282
        whilenewscroll = mapmiddle_px;
283
 
284
        newOffscreenImage();
285
 
286
    }
287
 
288
    bool LayerManager::checkOffscreen() const
289
    {
290
        // calculate offscreenImage dimension (px)
291
        QPoint upperLeft = mapmiddle_px - screenmiddle;
292
        QPoint lowerRight = mapmiddle_px + screenmiddle;
293
        QRect viewport = QRect(upperLeft, lowerRight);
294
 
295
        QRect testRect = layer()->offscreenViewport();
296
 
297
        if (!testRect.contains(viewport))
298
        {
299
            return false;
300
        }
301
 
302
        return true;
303
    }
304
    void LayerManager::zoomOut()
305
    {
306
        QCoreApplication::processEvents();
307
        ImageManager::instance()->abortLoading();
308
        zoomImageScroll = QPoint(0,0);
309
        zoomImage.fill(Qt::white);
310
        QPixmap tmpImg = composedOffscreenImage.copy(screenmiddle.x()+scroll.x(),screenmiddle.y()+scroll.y(), size.width(), size.height());
311
        QPainter painter(&zoomImage);
312
        painter.translate(screenmiddle);
313
        painter.scale(0.500001,0.500001);
314
        painter.translate(-screenmiddle);
315
        painter.drawPixmap(0,0,tmpImg);
316
 
317
        painter.translate(screenmiddle);
318
        painter.scale(2,2);
319
        painter.translate(-screenmiddle);
320
 
321
        QListIterator<Layer*> it(mylayers);
322
        //TODO: remove hack, that mapadapters wont get set zoom multiple times
323
        QList<const MapAdapter*> doneadapters;
324
        while (it.hasNext())
325
        {
326
            Layer* l = it.next();
327
            if (!doneadapters.contains(l->mapadapter()))
328
            {
329
                l->zoomOut();
330
                doneadapters.append(l->mapadapter());
331
            }
332
        }
333
        mapmiddle_px = layer()->mapadapter()->coordinateToDisplay(mapmiddle);
334
        whilenewscroll = mapmiddle_px;
335
        newOffscreenImage();
336
    }
337
 
338
    void LayerManager::setZoom(int zoomlevel)
339
    {
340
        int current_zoom;
341
        if (layer()->mapadapter()->minZoom() < layer()->mapadapter()->maxZoom())
342
        {
343
            current_zoom = layer()->mapadapter()->currentZoom();
344
        }
345
        else
346
        {
347
            current_zoom = layer()->mapadapter()->minZoom() - layer()->mapadapter()->currentZoom();
348
        }
349
 
350
 
351
        if (zoomlevel < current_zoom)
352
        {
353
            for (int i=current_zoom; i>zoomlevel; i--)
354
            {
355
                zoomOut();
356
            }
357
        }
358
        else
359
        {
360
            for (int i=current_zoom; i<zoomlevel; i++)
361
            {
362
                zoomIn();
363
            }
364
        }
365
    }
366
 
367
    void LayerManager::mouseEvent(const QMouseEvent* evnt)
368
    {
369
        QListIterator<Layer*> it(mylayers);
370
        while (it.hasNext())
371
        {
372
            Layer* l = it.next();
373
            if (l->isVisible())
374
            {
375
                l->mouseEvent(evnt, mapmiddle_px);
376
            }
377
        }
378
    }
379
 
380
    void LayerManager::updateRequest(QRectF rect)
381
    {
382
        const QPoint topleft = mapmiddle_px - screenmiddle;
383
 
384
        QPointF c = rect.topLeft();
385
 
386
        if (getViewport().contains(c) || getViewport().contains(rect.bottomRight()))
387
        {
388
            // QPoint point = getLayer()->getMapAdapter()->coordinateToDisplay(c);
389
            // QPoint finalpoint = point-topleft;
390
            // QRect rect_px = QRect(int(finalpoint.x()-(rect.width()-1)/2), int(finalpoint.y()-(rect.height()-1)/2),
391
            //  int(rect.width()+1), int(rect.height()+1));
392
            //
393
            // mapcontrol->updateRequest(rect_px);
394
            mapcontrol->update();
395
            // newOffscreenImage();
396
        }
397
    }
398
    void LayerManager::updateRequest()
399
    {
400
        newOffscreenImage();
401
    }
402
    void LayerManager::forceRedraw()
403
    {
404
        newOffscreenImage();
405
    }
406
    void LayerManager::removeZoomImage()
407
    {
408
        zoomImage.fill(Qt::white);
409
        forceRedraw();
410
    }
411
 
412
    void LayerManager::drawGeoms(QPainter* painter)
413
    {
414
        QListIterator<Layer*> it(mylayers);
415
        while (it.hasNext())
416
        {
417
            Layer* l = it.next();
418
            if (l->layertype() == Layer::GeometryLayer && l->isVisible())
419
            {
420
                l->drawYourGeometries(painter, mapmiddle_px, layer()->offscreenViewport());
421
            }
422
        }
423
    }
424
    void LayerManager::drawImage(QPainter* painter)
425
    {
426
        painter->drawPixmap(-scroll.x()-screenmiddle.x(),
427
                            -scroll.y()-screenmiddle.y(),
428
                            composedOffscreenImage);
429
    }
430
 
431
    int LayerManager::currentZoom() const
432
    {
433
        return layer()->mapadapter()->currentZoom();
434
    }
435
 
436
    void LayerManager::resize(QSize newSize)
437
    {
438
        size = newSize;
439
        offSize = newSize *2;
440
        composedOffscreenImage = QPixmap(offSize);
441
        composedOffscreenImage2 = QPixmap(offSize);
442
        zoomImage = QPixmap(newSize);
443
        zoomImage.fill(Qt::white);
444
 
445
        screenmiddle = QPoint(newSize.width()/2, newSize.height()/2);
446
 
447
        QListIterator<Layer*> it(mylayers);
448
        while (it.hasNext())
449
        {
450
            Layer* l = it.next();
451
            l->setSize(newSize);
452
        }
453
 
454
        newOffscreenImage();
455
    }
456
}